http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SavingsTransactionDTO.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SavingsTransactionDTO.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SavingsTransactionDTO.java
index 0ee7b11..567ef2d 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SavingsTransactionDTO.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SavingsTransactionDTO.java
@@ -41,13 +41,14 @@ public class SavingsTransactionDTO {
     /** Breakdowns of fees and penalties this Transaction pays **/
     private final List<ChargePaymentDTO> penaltyPayments;
     private final List<ChargePaymentDTO> feePayments;
+    private final List<TaxPaymentDTO> taxPayments;
 
     private final boolean isAccountTransfer;
 
     public SavingsTransactionDTO(final Long officeId, final Long 
paymentTypeId, final String transactionId, final Date transactionDate,
             final SavingsAccountTransactionEnumData transactionType, final 
BigDecimal amount, final boolean reversed,
             final List<ChargePaymentDTO> feePayments, final 
List<ChargePaymentDTO> penaltyPayments, final BigDecimal overdraftAmount,
-            boolean isAccountTransfer) {
+            boolean isAccountTransfer, final List<TaxPaymentDTO> taxPayments) {
         this.paymentTypeId = paymentTypeId;
         this.transactionId = transactionId;
         this.transactionDate = transactionDate;
@@ -59,6 +60,7 @@ public class SavingsTransactionDTO {
         this.officeId = officeId;
         this.overdraftAmount = overdraftAmount;
         this.isAccountTransfer = isAccountTransfer;
+        this.taxPayments = taxPayments;
     }
 
     public Long getOfficeId() {
@@ -109,4 +111,8 @@ public class SavingsTransactionDTO {
         return this.isAccountTransfer;
     }
 
+    public List<TaxPaymentDTO> getTaxPayments() {
+        return this.taxPayments;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/TaxPaymentDTO.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/TaxPaymentDTO.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/TaxPaymentDTO.java
new file mode 100644
index 0000000..e9e1d34
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/TaxPaymentDTO.java
@@ -0,0 +1,47 @@
+/**
+ * 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.accounting.journalentry.data;
+
+import java.math.BigDecimal;
+
+public class TaxPaymentDTO {
+
+    private final Long creditAccountId;
+    private final Long debitAccountId;
+    private final BigDecimal amount;
+
+    public TaxPaymentDTO(final Long debitAccountId, final Long 
creditAccountId, final BigDecimal amount) {
+        this.debitAccountId = debitAccountId;
+        this.creditAccountId = creditAccountId;
+        this.amount = amount;
+    }
+
+    public Long getCreditAccountId() {
+        return this.creditAccountId;
+    }
+
+    public Long getDebitAccountId() {
+        return this.debitAccountId;
+    }
+
+    public BigDecimal getAmount() {
+        return this.amount;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
index 575cd86..fb9c799 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
@@ -43,6 +43,7 @@ import 
org.apache.fineract.accounting.journalentry.data.LoanDTO;
 import org.apache.fineract.accounting.journalentry.data.LoanTransactionDTO;
 import org.apache.fineract.accounting.journalentry.data.SavingsDTO;
 import org.apache.fineract.accounting.journalentry.data.SavingsTransactionDTO;
+import org.apache.fineract.accounting.journalentry.data.TaxPaymentDTO;
 import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
 import 
org.apache.fineract.accounting.journalentry.domain.JournalEntryRepository;
 import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
@@ -78,7 +79,7 @@ public class AccountingProcessorHelper {
     public static final String LOAN_TRANSACTION_IDENTIFIER = "L";
     public static final String SAVINGS_TRANSACTION_IDENTIFIER = "S";
     public static final String CLIENT_TRANSACTION_IDENTIFIER = "C";
-    public static final String PROVISIONING_TRANSACTION_IDENTIFIER = "P" ;
+    public static final String PROVISIONING_TRANSACTION_IDENTIFIER = "P";
     private final JournalEntryRepository glJournalEntryRepository;
     private final ProductToGLAccountMappingRepository accountMappingRepository;
     private final FinancialActivityAccountRepositoryWrapper 
financialActivityAccountRepository;
@@ -214,12 +215,26 @@ public class AccountingProcessorHelper {
                     }
                 }
             }
+
+            final List<TaxPaymentDTO> taxPayments = new ArrayList<>();
+            if (map.containsKey("taxDetails")) {
+                @SuppressWarnings("unchecked")
+                final List<Map<String, Object>> taxDatas = (List<Map<String, 
Object>>) map.get("taxDetails");
+                for (final Map<String, Object> taxData : taxDatas) {
+                    final BigDecimal taxAmount = (BigDecimal) 
taxData.get("amount");
+                    final Long creditAccountId = (Long) 
taxData.get("creditAccountId");
+                    final Long debitAccountId = (Long) 
taxData.get("debitAccountId");
+                    taxPayments.add(new TaxPaymentDTO(debitAccountId, 
creditAccountId, taxAmount));
+                }
+            }
+
             if (!isAccountTransfer) {
                 isAccountTransfer = 
this.accountTransfersReadPlatformService.isAccountTransfer(Long.parseLong(transactionId),
                         PortfolioAccountType.SAVINGS);
             }
             final SavingsTransactionDTO transaction = new 
SavingsTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
-                    transactionDate, transactionType, amount, reversed, 
feePayments, penaltyPayments, overdraftAmount, isAccountTransfer);
+                    transactionDate, transactionType, amount, reversed, 
feePayments, penaltyPayments, overdraftAmount, isAccountTransfer,
+                    taxPayments);
 
             newSavingsTransactions.add(transaction);
 
@@ -254,15 +269,14 @@ public class AccountingProcessorHelper {
                 final boolean isPenalty = (Boolean) 
clientChargePaid.get("isPenalty");
                 final BigDecimal chargeAmountPaid = (BigDecimal) 
clientChargePaid.get("amount");
                 final Long incomeAccountId = (Long) 
clientChargePaid.get("incomeAccountId");
-                final ClientChargePaymentDTO clientChargePaymentDTO = new 
ClientChargePaymentDTO(chargeId, chargeAmountPaid, clientChargeId,
-                        isPenalty, incomeAccountId);
+                final ClientChargePaymentDTO clientChargePaymentDTO = new 
ClientChargePaymentDTO(chargeId, chargeAmountPaid,
+                        clientChargeId, isPenalty, incomeAccountId);
                 clientChargePaymentDTOs.add(clientChargePaymentDTO);
             }
         }
 
         final ClientTransactionDTO clientTransactionDTO = new 
ClientTransactionDTO(clientId, transactionOfficeId, paymentTypeId,
-                transactionId, transactionDate, transactionType, currencyCode, 
amount, reversed, accountingEnabled,
-                clientChargePaymentDTOs);
+                transactionId, transactionDate, transactionType, currencyCode, 
amount, reversed, accountingEnabled, clientChargePaymentDTOs);
 
         return clientTransactionDTO;
 
@@ -289,8 +303,9 @@ public class AccountingProcessorHelper {
      * @param isReversal
      */
     public void createAccrualBasedJournalEntriesAndReversalsForLoan(final 
Office office, final String currencyCode,
-            final Integer accountTypeToBeDebited, final Integer 
accountTypeToBeCredited, final Long loanProductId, final Long paymentTypeId,
-            final Long loanId, final String transactionId, final Date 
transactionDate, final BigDecimal amount, final Boolean isReversal) {
+            final Integer accountTypeToBeDebited, final Integer 
accountTypeToBeCredited, final Long loanProductId,
+            final Long paymentTypeId, final Long loanId, final String 
transactionId, final Date transactionDate, final BigDecimal amount,
+            final Boolean isReversal) {
         int accountTypeToDebitId = accountTypeToBeDebited;
         int accountTypeToCreditId = accountTypeToBeCredited;
         // reverse debits and credits for reversals
@@ -298,8 +313,8 @@ public class AccountingProcessorHelper {
             accountTypeToDebitId = accountTypeToBeCredited;
             accountTypeToCreditId = accountTypeToBeDebited;
         }
-        createJournalEntriesForLoan(office, currencyCode, 
accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, 
loanId,
-                transactionId, transactionDate, amount);
+        createJournalEntriesForLoan(office, currencyCode, 
accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
+                loanId, transactionId, transactionDate, amount);
     }
 
     /**
@@ -419,8 +434,9 @@ public class AccountingProcessorHelper {
      * @param isReversal
      */
     public void createCashBasedJournalEntriesAndReversalsForLoan(final Office 
office, final String currencyCode,
-            final Integer accountTypeToBeDebited, final Integer 
accountTypeToBeCredited, final Long loanProductId, final Long paymentTypeId,
-            final Long loanId, final String transactionId, final Date 
transactionDate, final BigDecimal amount, final Boolean isReversal) {
+            final Integer accountTypeToBeDebited, final Integer 
accountTypeToBeCredited, final Long loanProductId,
+            final Long paymentTypeId, final Long loanId, final String 
transactionId, final Date transactionDate, final BigDecimal amount,
+            final Boolean isReversal) {
         int accountTypeToDebitId = accountTypeToBeDebited;
         int accountTypeToCreditId = accountTypeToBeCredited;
         // reverse debits and credits for reversals
@@ -428,8 +444,8 @@ public class AccountingProcessorHelper {
             accountTypeToDebitId = accountTypeToBeCredited;
             accountTypeToCreditId = accountTypeToBeDebited;
         }
-        createJournalEntriesForLoan(office, currencyCode, 
accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, 
loanId,
-                transactionId, transactionDate, amount);
+        createJournalEntriesForLoan(office, currencyCode, 
accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
+                loanId, transactionId, transactionDate, amount);
     }
 
     public void createCreditJournalEntryOrReversalForLoan(final Office office, 
final String currencyCode,
@@ -458,9 +474,8 @@ public class AccountingProcessorHelper {
          * transaction Date
          **/
         if (latestGLClosure != null) {
-            if (latestGLClosure.getClosingDate().after(transactionDate)
-                    || 
latestGLClosure.getClosingDate().equals(transactionDate)) { throw new 
JournalEntryInvalidException(
-                            GL_JOURNAL_ENTRY_INVALID_REASON.ACCOUNTING_CLOSED, 
latestGLClosure.getClosingDate(), null, null); }
+            if (latestGLClosure.getClosingDate().after(transactionDate) || 
latestGLClosure.getClosingDate().equals(transactionDate)) { throw new 
JournalEntryInvalidException(
+                    GL_JOURNAL_ENTRY_INVALID_REASON.ACCOUNTING_CLOSED, 
latestGLClosure.getClosingDate(), null, null); }
         }
     }
 
@@ -490,6 +505,111 @@ public class AccountingProcessorHelper {
         createCreditJournalEntryForSavings(office, currencyCode, 
creditAccount, savingsId, transactionId, transactionDate, amount);
     }
 
+    /**
+     * Convenience method that creates a pair of related Debits and Credits for
+     * Cash Based accounting.
+     * 
+     * The target accounts for debits and credits are switched in case of a
+     * reversal
+     * 
+     * @param office
+     * @param accountTypeToBeDebited
+     *            Enum of the placeholder GLAccount to be debited
+     * @param accountTypeToBeCredited
+     *            Enum of the placeholder of the GLAccount to be credited
+     * @param savingsProductId
+     * @param paymentTypeId
+     * @param loanId
+     * @param transactionId
+     * @param transactionDate
+     * @param amount
+     * @param isReversal
+     */
+    public void createCashBasedJournalEntriesAndReversalsForSavingsTax(final 
Office office, final String currencyCode,
+            final CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeDebited, final 
CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeCredited,
+            final Long savingsProductId, final Long paymentTypeId, final Long 
savingsId, final String transactionId,
+            final Date transactionDate, final BigDecimal amount, final Boolean 
isReversal, final List<TaxPaymentDTO> taxDetails) {
+
+        for (TaxPaymentDTO taxPaymentDTO : taxDetails) {
+            if (taxPaymentDTO.getAmount() != null) {
+                if (taxPaymentDTO.getCreditAccountId() == null) {
+                    
createCashBasedCreditJournalEntriesAndReversalsForSavings(office, currencyCode, 
accountTypeToBeCredited.getValue(),
+                            savingsProductId, paymentTypeId, savingsId, 
transactionId, transactionDate, taxPaymentDTO.getAmount(),
+                            isReversal);
+                } else {
+                    
createCashBasedCreditJournalEntriesAndReversalsForSavings(office, currencyCode, 
taxPaymentDTO.getCreditAccountId(),
+                            savingsId, transactionId, transactionDate, 
taxPaymentDTO.getAmount(), isReversal);
+                }
+            }
+        }
+        createCashBasedDebitJournalEntriesAndReversalsForSavings(office, 
currencyCode, accountTypeToBeDebited.getValue(), savingsProductId,
+                paymentTypeId, savingsId, transactionId, transactionDate, 
amount, isReversal);
+    }
+
+    public void createCashBasedDebitJournalEntriesAndReversalsForSavings(final 
Office office, final String currencyCode,
+            final Integer accountTypeToBeDebited, final Long savingsProductId, 
final Long paymentTypeId, final Long savingsId,
+            final String transactionId, final Date transactionDate, final 
BigDecimal amount, final Boolean isReversal) {
+        // reverse debits and credits for reversals
+        if (isReversal) {
+            createCreditJournalEntriesForSavings(office, currencyCode, 
accountTypeToBeDebited, savingsProductId, paymentTypeId, savingsId,
+                    transactionId, transactionDate, amount);
+        } else {
+            createDebitJournalEntriesForSavings(office, currencyCode, 
accountTypeToBeDebited, savingsProductId, paymentTypeId, savingsId,
+                    transactionId, transactionDate, amount);
+        }
+    }
+
+    public void 
createCashBasedCreditJournalEntriesAndReversalsForSavings(final Office office, 
final String currencyCode,
+            final Integer accountTypeToBeCredited, final Long 
savingsProductId, final Long paymentTypeId, final Long savingsId,
+            final String transactionId, final Date transactionDate, final 
BigDecimal amount, final Boolean isReversal) {
+        // reverse debits and credits for reversals
+        if (isReversal) {
+            createDebitJournalEntriesForSavings(office, currencyCode, 
accountTypeToBeCredited, savingsProductId, paymentTypeId, savingsId,
+                    transactionId, transactionDate, amount);
+        } else {
+            createCreditJournalEntriesForSavings(office, currencyCode, 
accountTypeToBeCredited, savingsProductId, paymentTypeId, savingsId,
+                    transactionId, transactionDate, amount);
+        }
+    }
+
+    public void createCashBasedDebitJournalEntriesAndReversalsForSavings(final 
Office office, final String currencyCode,
+            final Long debitAccountId, final Long savingsId, final String 
transactionId, final Date transactionDate,
+            final BigDecimal amount, final Boolean isReversal) {
+        // reverse debits and credits for reversals
+        final GLAccount debitAccount = getGLAccountById(debitAccountId);
+        if (isReversal) {
+            createCreditJournalEntryForSavings(office, currencyCode, 
debitAccount, savingsId, transactionId, transactionDate, amount);
+        } else {
+            createDebitJournalEntryForSavings(office, currencyCode, 
debitAccount, savingsId, transactionId, transactionDate, amount);
+        }
+    }
+
+    public void 
createCashBasedCreditJournalEntriesAndReversalsForSavings(final Office office, 
final String currencyCode,
+            final Long creditAccountId, final Long savingsId, final String 
transactionId, final Date transactionDate,
+            final BigDecimal amount, final Boolean isReversal) {
+        // reverse debits and credits for reversals
+        final GLAccount creditAccount = getGLAccountById(creditAccountId);
+        if (isReversal) {
+            createDebitJournalEntryForSavings(office, currencyCode, 
creditAccount, savingsId, transactionId, transactionDate, amount);
+        } else {
+            createCreditJournalEntryForSavings(office, currencyCode, 
creditAccount, savingsId, transactionId, transactionDate, amount);
+        }
+    }
+
+    private void createDebitJournalEntriesForSavings(final Office office, 
final String currencyCode, final int accountTypeToDebitId,
+            final Long savingsProductId, final Long paymentTypeId, final Long 
savingsId, final String transactionId,
+            final Date transactionDate, final BigDecimal amount) {
+        final GLAccount debitAccount = 
getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToDebitId, 
paymentTypeId);
+        createDebitJournalEntryForSavings(office, currencyCode, debitAccount, 
savingsId, transactionId, transactionDate, amount);
+    }
+
+    private void createCreditJournalEntriesForSavings(final Office office, 
final String currencyCode, final int accountTypeToCreditId,
+            final Long savingsProductId, final Long paymentTypeId, final Long 
savingsId, final String transactionId,
+            final Date transactionDate, final BigDecimal amount) {
+        final GLAccount creditAccount = 
getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToCreditId, 
paymentTypeId);
+        createCreditJournalEntryForSavings(office, currencyCode, 
creditAccount, savingsId, transactionId, transactionDate, amount);
+    }
+
     public void createDebitJournalEntryOrReversalForLoan(final Office office, 
final String currencyCode, final int accountMappingTypeId,
             final Long loanProductId, final Long paymentTypeId, final Long 
loanId, final String transactionId, final Date transactionDate,
             final BigDecimal amount, final Boolean isReversal) {
@@ -631,8 +751,8 @@ public class AccountingProcessorHelper {
         String modifiedTransactionId = transactionId.toString();
         modifiedTransactionId = CLIENT_TRANSACTION_IDENTIFIER + transactionId;
         final JournalEntry journalEntry = JournalEntry.createNew(office, 
paymentDetail, account, currencyCode, modifiedTransactionId,
-                manualEntry, transactionDate, JournalEntryType.CREDIT, amount, 
null, PortfolioProductType.CLIENT.getValue(), clientId, null,
-                loanTransaction, savingsAccountTransaction, clientTransaction);
+                manualEntry, transactionDate, JournalEntryType.CREDIT, amount, 
null, PortfolioProductType.CLIENT.getValue(), clientId,
+                null, loanTransaction, savingsAccountTransaction, 
clientTransaction);
         this.glJournalEntryRepository.saveAndFlush(journalEntry);
     }
 
@@ -655,8 +775,8 @@ public class AccountingProcessorHelper {
         this.glJournalEntryRepository.saveAndFlush(journalEntry);
     }
 
-    private void createCreditJournalEntryForLoan(final Office office, final 
String currencyCode, final GLAccount account, final Long loanId,
-            final String transactionId, final Date transactionDate, final 
BigDecimal amount) {
+    private void createCreditJournalEntryForLoan(final Office office, final 
String currencyCode, final GLAccount account,
+            final Long loanId, final String transactionId, final Date 
transactionDate, final BigDecimal amount) {
         final boolean manualEntry = false;
         LoanTransaction loanTransaction = null;
         SavingsAccountTransaction savingsAccountTransaction = null;
@@ -674,33 +794,35 @@ public class AccountingProcessorHelper {
         this.glJournalEntryRepository.saveAndFlush(journalEntry);
     }
 
-    public void createProvisioningDebitJournalEntry(Date transactionDate, Long 
provisioningentryId, Office office, String currencyCode, GLAccount 
account,BigDecimal amount) {
+    public void createProvisioningDebitJournalEntry(Date transactionDate, Long 
provisioningentryId, Office office, String currencyCode,
+            GLAccount account, BigDecimal amount) {
         LoanTransaction loanTransaction = null;
         SavingsAccountTransaction savingsAccountTransaction = null;
         ClientTransaction clientTransaction = null;
-        PaymentDetail paymentDetail = null ;
+        PaymentDetail paymentDetail = null;
         final boolean manualEntry = false;
         String modifiedTransactionId = PROVISIONING_TRANSACTION_IDENTIFIER + 
provisioningentryId;
         final JournalEntry journalEntry = JournalEntry.createNew(office, 
paymentDetail, account, currencyCode, modifiedTransactionId,
-                manualEntry, transactionDate, JournalEntryType.DEBIT, amount, 
null, PortfolioProductType.PROVISIONING.getValue(), provisioningentryId, null,
-                loanTransaction, savingsAccountTransaction, clientTransaction);
-        
+                manualEntry, transactionDate, JournalEntryType.DEBIT, amount, 
null, PortfolioProductType.PROVISIONING.getValue(),
+                provisioningentryId, null, loanTransaction, 
savingsAccountTransaction, clientTransaction);
+
         this.glJournalEntryRepository.saveAndFlush(journalEntry);
     }
-    
-    public void createProvisioningCreditJournalEntry(Date transactionDate, 
Long provisioningentryId, Office office, String currencyCode, GLAccount 
account, BigDecimal amount) {
+
+    public void createProvisioningCreditJournalEntry(Date transactionDate, 
Long provisioningentryId, Office office, String currencyCode,
+            GLAccount account, BigDecimal amount) {
         LoanTransaction loanTransaction = null;
         SavingsAccountTransaction savingsAccountTransaction = null;
         ClientTransaction clientTransaction = null;
-        PaymentDetail paymentDetail = null ;
+        PaymentDetail paymentDetail = null;
         final boolean manualEntry = false;
         String modifiedTransactionId = PROVISIONING_TRANSACTION_IDENTIFIER + 
provisioningentryId;
         final JournalEntry journalEntry = JournalEntry.createNew(office, 
paymentDetail, account, currencyCode, modifiedTransactionId,
-                manualEntry, transactionDate, JournalEntryType.CREDIT, amount, 
null, PortfolioProductType.PROVISIONING.getValue(), provisioningentryId, null,
-                loanTransaction, savingsAccountTransaction, clientTransaction);
+                manualEntry, transactionDate, JournalEntryType.CREDIT, amount, 
null, PortfolioProductType.PROVISIONING.getValue(),
+                provisioningentryId, null, loanTransaction, 
savingsAccountTransaction, clientTransaction);
         this.glJournalEntryRepository.saveAndFlush(journalEntry);
     }
-    
+
     private void createDebitJournalEntryForLoan(final Office office, final 
String currencyCode, final GLAccount account, final Long loanId,
             final String transactionId, final Date transactionDate, final 
BigDecimal amount) {
         final boolean manualEntry = false;
@@ -734,8 +856,8 @@ public class AccountingProcessorHelper {
             modifiedTransactionId = SAVINGS_TRANSACTION_IDENTIFIER + 
transactionId;
         }
         final JournalEntry journalEntry = JournalEntry.createNew(office, 
paymentDetail, account, currencyCode, modifiedTransactionId,
-                manualEntry, transactionDate, JournalEntryType.DEBIT, amount, 
null, PortfolioProductType.SAVING.getValue(), savingsId, null,
-                loanTransaction, savingsAccountTransaction, clientTransaction);
+                manualEntry, transactionDate, JournalEntryType.DEBIT, amount, 
null, PortfolioProductType.SAVING.getValue(), savingsId,
+                null, loanTransaction, savingsAccountTransaction, 
clientTransaction);
         this.glJournalEntryRepository.saveAndFlush(journalEntry);
     }
 
@@ -791,13 +913,12 @@ public class AccountingProcessorHelper {
     private GLAccount getLinkedGLAccountForLoanCharges(final Long 
loanProductId, final int accountMappingTypeId, final Long chargeId) {
         ProductToGLAccountMapping accountMapping = 
this.accountMappingRepository.findCoreProductToFinAccountMapping(loanProductId,
                 PortfolioProductType.LOAN.getValue(), accountMappingTypeId);
-                /*****
-                 * Get more specific mappings for Charges and penalties (based
-                 * on the actual charge /penalty coupled with the loan 
product).
-                 * Note the income from fees and income from penalties
-                 * placeholder ID would be the same for both cash and accrual
-                 * based accounts
-                 *****/
+        /*****
+         * Get more specific mappings for Charges and penalties (based on the
+         * actual charge /penalty coupled with the loan product). Note the
+         * income from fees and income from penalties placeholder ID would be
+         * the same for both cash and accrual based accounts
+         *****/
 
         // Vishwas TODO: remove this condition as it should always be true
         if (accountMappingTypeId == 
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue()
@@ -812,17 +933,15 @@ public class AccountingProcessorHelper {
         return accountMapping.getGlAccount();
     }
 
-    private GLAccount getLinkedGLAccountForSavingsCharges(final Long 
savingsProductId, final int accountMappingTypeId,
-            final Long chargeId) {
+    private GLAccount getLinkedGLAccountForSavingsCharges(final Long 
savingsProductId, final int accountMappingTypeId, final Long chargeId) {
         ProductToGLAccountMapping accountMapping = 
this.accountMappingRepository.findCoreProductToFinAccountMapping(savingsProductId,
                 PortfolioProductType.SAVING.getValue(), accountMappingTypeId);
-                /*****
-                 * Get more specific mappings for Charges and penalties (based
-                 * on the actual charge /penalty coupled with the loan 
product).
-                 * Note the income from fees and income from penalties
-                 * placeholder ID would be the same for both cash and accrual
-                 * based accounts
-                 *****/
+        /*****
+         * Get more specific mappings for Charges and penalties (based on the
+         * actual charge /penalty coupled with the loan product). Note the
+         * income from fees and income from penalties placeholder ID would be
+         * the same for both cash and accrual based accounts
+         *****/
 
         // Vishwas TODO: remove this condition as it should always be true
         if (accountMappingTypeId == 
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES.getValue()
@@ -912,8 +1031,8 @@ public class AccountingProcessorHelper {
 
     public void createDebitJournalEntryOrReversalForClientChargePayments(final 
Office office, final String currencyCode,
             final Long clientId, final Long transactionId, final Date 
transactionDate, final BigDecimal amount, final Boolean isReversal) {
-        final GLAccount account = financialActivityAccountRepository
-                
.findByFinancialActivityTypeWithNotFoundDetection(FINANCIAL_ACTIVITY.ASSET_FUND_SOURCE.getValue()).getGlAccount();
+        final GLAccount account = 
financialActivityAccountRepository.findByFinancialActivityTypeWithNotFoundDetection(
+                
FINANCIAL_ACTIVITY.ASSET_FUND_SOURCE.getValue()).getGlAccount();
         if (isReversal) {
             createCreditJournalEntryForClientPayments(office, currencyCode, 
account, clientId, transactionId, transactionDate, amount);
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java
index 2b8198a..27eb9e8 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java
@@ -168,6 +168,13 @@ public class CashBasedAccountingProcessorForSavings 
implements AccountingProcess
                 }
             }
 
+            else if 
(savingsTransactionDTO.getTransactionType().isWithholdTax()) {
+                
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsTax(office, 
currencyCode,
+                        CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, 
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId,
+                        paymentTypeId, savingsId, transactionId, 
transactionDate, amount, isReversal,
+                        savingsTransactionDTO.getTaxPayments());
+            }
+
             /** Handle Fees Deductions and reversals of Fees Deductions **/
             else if 
(savingsTransactionDTO.getTransactionType().isFeeDeduction() && 
savingsTransactionDTO.isOverdraftTransaction()) {
                 // Is the Charge a penalty?

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
 
b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index d532049..cc33ecc 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -2616,4 +2616,44 @@ public class CommandWrapperBuilder {
         this.href = "/accounts/" + accountType+"/"+accountId;
         return this;
     }
+    
+    public CommandWrapperBuilder createTaxComponent() {
+        this.actionName = "CREATE";
+        this.entityName = "TAXCOMPONENT";
+        this.entityId = null;
+        this.href = "/taxes/component";
+        return this;
+    }
+
+    public CommandWrapperBuilder updateTaxComponent(final Long taxComponentId) 
{
+        this.actionName = "UPDATE";
+        this.entityName = "TAXCOMPONENT";
+        this.entityId = taxComponentId;
+        this.href = "/taxes/component/" + taxComponentId;
+        return this;
+    }
+
+    public CommandWrapperBuilder createTaxGroup() {
+        this.actionName = "CREATE";
+        this.entityName = "TAXGROUP";
+        this.entityId = null;
+        this.href = "/taxes/group";
+        return this;
+    }
+
+    public CommandWrapperBuilder updateTaxGroup(final Long taxGroupId) {
+        this.actionName = "UPDATE";
+        this.entityName = "TAXGROUP";
+        this.entityId = taxGroupId;
+        this.href = "/taxes/group/" + taxGroupId;
+        return this;
+    }
+    
+    public CommandWrapperBuilder updateWithHoldTax(final Long accountId) {
+        this.actionName = "UPDATEWITHHOLDTAX";
+        this.entityName = "SAVINGSACCOUNT";
+        this.entityId = accountId;
+        this.href = "/savingsaccounts/" + accountId + 
"?commad=updateTaxWithHoldTax";
+        return this;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiConstants.java
index 01488dd..7e3526e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiConstants.java
@@ -21,5 +21,6 @@ package org.apache.fineract.portfolio.charge.api;
 public class ChargesApiConstants {
 
     public static final String glAccountIdParamName = "incomeAccountId";
+    public static final String taxGroupIdParamName = "taxGroupId";
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
index a818bd3..28bcd74 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
@@ -30,6 +30,7 @@ import 
org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
 import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
+import org.apache.fineract.portfolio.tax.data.TaxGroupData;
 import org.joda.time.LocalDate;
 import org.joda.time.MonthDay;
 
@@ -54,6 +55,7 @@ public class ChargeData implements Comparable<ChargeData>, 
Serializable {
     private final BigDecimal maxCap;
     private final EnumOptionData feeFrequency;
     private final GLAccountData incomeOrLiabilityAccount;
+    private final TaxGroupData taxGroup;
 
     private final Collection<CurrencyData> currencyOptions;
     private final List<EnumOptionData> chargeCalculationTypeOptions;//
@@ -70,6 +72,7 @@ public class ChargeData implements Comparable<ChargeData>, 
Serializable {
     private final List<EnumOptionData> feeFrequencyOptions;
 
     private final Map<String, List<GLAccountData>> 
incomeOrLiabilityAccountOptions;
+    private final Collection<TaxGroupData> taxGroupOptions;
 
     public static ChargeData template(final Collection<CurrencyData> 
currencyOptions,
             final List<EnumOptionData> chargeCalculationTypeOptions, final 
List<EnumOptionData> chargeAppliesToOptions,
@@ -77,31 +80,33 @@ public class ChargeData implements Comparable<ChargeData>, 
Serializable {
             final List<EnumOptionData> loansChargeCalculationTypeOptions, 
final List<EnumOptionData> loansChargeTimeTypeOptions,
             final List<EnumOptionData> savingsChargeCalculationTypeOptions, 
final List<EnumOptionData> savingsChargeTimeTypeOptions,
             final List<EnumOptionData> clientChargeCalculationTypeOptions, 
final List<EnumOptionData> clientChargeTimeTypeOptions,
-            final List<EnumOptionData> feeFrequencyOptions, final Map<String, 
List<GLAccountData>> incomeOrLiabilityAccountOptions) {
+            final List<EnumOptionData> feeFrequencyOptions, final Map<String, 
List<GLAccountData>> incomeOrLiabilityAccountOptions,
+            final Collection<TaxGroupData> taxGroupOptions) {
         final GLAccountData account = null;
-        return new ChargeData(null, null, null, null, null, null, null, null, 
false, false, currencyOptions, chargeCalculationTypeOptions,
-                chargeAppliesToOptions, chargeTimeTypeOptions, 
chargePaymentModeOptions, loansChargeCalculationTypeOptions,
-                loansChargeTimeTypeOptions, 
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions,
-                clientChargeCalculationTypeOptions, 
clientChargeTimeTypeOptions, null, null, null, null, null, feeFrequencyOptions, 
account,
-                incomeOrLiabilityAccountOptions);
+        final TaxGroupData taxGroupData = null;
+        return new ChargeData(null, null, null, null, null, null, null, null, 
false, false, taxGroupData, currencyOptions,
+                chargeCalculationTypeOptions, chargeAppliesToOptions, 
chargeTimeTypeOptions, chargePaymentModeOptions,
+                loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, 
savingsChargeCalculationTypeOptions,
+                savingsChargeTimeTypeOptions, 
clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, 
null, null,
+                null, feeFrequencyOptions, account, 
incomeOrLiabilityAccountOptions, taxGroupOptions);
     }
 
     public static ChargeData withTemplate(final ChargeData charge, final 
ChargeData template) {
         return new ChargeData(charge.id, charge.name, charge.amount, 
charge.currency, charge.chargeTimeType, charge.chargeAppliesTo,
-                charge.chargeCalculationType, charge.chargePaymentMode, 
charge.penalty, charge.active, template.currencyOptions,
-                template.chargeCalculationTypeOptions, 
template.chargeAppliesToOptions, template.chargeTimeTypeOptions,
-                template.chargePaymetModeOptions, 
template.loanChargeCalculationTypeOptions, template.loanChargeTimeTypeOptions,
-                template.savingsChargeCalculationTypeOptions, 
template.savingsChargeTimeTypeOptions,
-                template.clientChargeCalculationTypeOptions, 
template.clientChargeTimeTypeOptions, charge.feeOnMonthDay, charge.feeInterval,
-                charge.minCap, charge.maxCap, charge.feeFrequency, 
template.feeFrequencyOptions, charge.incomeOrLiabilityAccount,
-                template.incomeOrLiabilityAccountOptions);
+                charge.chargeCalculationType, charge.chargePaymentMode, 
charge.penalty, charge.active, charge.taxGroup,
+                template.currencyOptions, 
template.chargeCalculationTypeOptions, template.chargeAppliesToOptions,
+                template.chargeTimeTypeOptions, 
template.chargePaymetModeOptions, template.loanChargeCalculationTypeOptions,
+                template.loanChargeTimeTypeOptions, 
template.savingsChargeCalculationTypeOptions, 
template.savingsChargeTimeTypeOptions,
+                template.clientChargeCalculationTypeOptions, 
template.clientChargeTimeTypeOptions, charge.feeOnMonthDay,
+                charge.feeInterval, charge.minCap, charge.maxCap, 
charge.feeFrequency, template.feeFrequencyOptions,
+                charge.incomeOrLiabilityAccount, 
template.incomeOrLiabilityAccountOptions, template.taxGroupOptions);
     }
 
     public static ChargeData instance(final Long id, final String name, final 
BigDecimal amount, final CurrencyData currency,
             final EnumOptionData chargeTimeType, final EnumOptionData 
chargeAppliesTo, final EnumOptionData chargeCalculationType,
             final EnumOptionData chargePaymentMode, final MonthDay 
feeOnMonthDay, final Integer feeInterval, final boolean penalty,
             final boolean active, final BigDecimal minCap, final BigDecimal 
maxCap, final EnumOptionData feeFrequency,
-            final GLAccountData accountData) {
+            final GLAccountData accountData, TaxGroupData taxGroupData) {
 
         final Collection<CurrencyData> currencyOptions = null;
         final List<EnumOptionData> chargeCalculationTypeOptions = null;
@@ -116,13 +121,14 @@ public class ChargeData implements 
Comparable<ChargeData>, Serializable {
         final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
         final List<EnumOptionData> clientChargeTimeTypeOptions = null;
         final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions 
= null;
+        final Collection<TaxGroupData> taxGroupOptions = null;
 
         return new ChargeData(id, name, amount, currency, chargeTimeType, 
chargeAppliesTo, chargeCalculationType, chargePaymentMode,
-                penalty, active, currencyOptions, 
chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
-                chargePaymentModeOptions, loansChargeCalculationTypeOptions, 
loansChargeTimeTypeOptions,
+                penalty, active, taxGroupData, currencyOptions, 
chargeCalculationTypeOptions, chargeAppliesToOptions,
+                chargeTimeTypeOptions, chargePaymentModeOptions, 
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
                 savingsChargeCalculationTypeOptions, 
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
                 clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, 
minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData,
-                incomeOrLiabilityAccountOptions);
+                incomeOrLiabilityAccountOptions, taxGroupOptions);
     }
 
     public static ChargeData lookup(final Long id, final String name, final 
boolean isPenalty) {
@@ -153,17 +159,19 @@ public class ChargeData implements 
Comparable<ChargeData>, Serializable {
         final List<EnumOptionData> feeFrequencyOptions = null;
         final GLAccountData account = null;
         final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions 
= null;
+        final TaxGroupData taxGroupData = null;
+        final Collection<TaxGroupData> taxGroupOptions = null;
         return new ChargeData(id, name, amount, currency, chargeTimeType, 
chargeAppliesTo, chargeCalculationType, chargePaymentMode,
-                penalty, active, currencyOptions, 
chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
-                chargePaymentModeOptions, loansChargeCalculationTypeOptions, 
loansChargeTimeTypeOptions,
+                penalty, active, taxGroupData, currencyOptions, 
chargeCalculationTypeOptions, chargeAppliesToOptions,
+                chargeTimeTypeOptions, chargePaymentModeOptions, 
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
                 savingsChargeCalculationTypeOptions, 
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
                 clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, 
minCap, maxCap, feeFrequency, feeFrequencyOptions, account,
-                incomeOrLiabilityAccountOptions);
+                incomeOrLiabilityAccountOptions, taxGroupOptions);
     }
 
     private ChargeData(final Long id, final String name, final BigDecimal 
amount, final CurrencyData currency,
             final EnumOptionData chargeTimeType, final EnumOptionData 
chargeAppliesTo, final EnumOptionData chargeCalculationType,
-            final EnumOptionData chargePaymentMode, final boolean penalty, 
final boolean active,
+            final EnumOptionData chargePaymentMode, final boolean penalty, 
final boolean active, final TaxGroupData taxGroupData,
             final Collection<CurrencyData> currencyOptions, final 
List<EnumOptionData> chargeCalculationTypeOptions,
             final List<EnumOptionData> chargeAppliesToOptions, final 
List<EnumOptionData> chargeTimeTypeOptions,
             final List<EnumOptionData> chargePaymentModeOptions, final 
List<EnumOptionData> loansChargeCalculationTypeOptions,
@@ -172,7 +180,7 @@ public class ChargeData implements Comparable<ChargeData>, 
Serializable {
             final List<EnumOptionData> clientChargeTimeTypeOptions, final 
MonthDay feeOnMonthDay, final Integer feeInterval,
             final BigDecimal minCap, final BigDecimal maxCap, final 
EnumOptionData feeFrequency,
             final List<EnumOptionData> feeFrequencyOptions, final 
GLAccountData account,
-            final Map<String, List<GLAccountData>> 
incomeOrLiabilityAccountOptions) {
+            final Map<String, List<GLAccountData>> 
incomeOrLiabilityAccountOptions, final Collection<TaxGroupData> 
taxGroupOptions) {
         this.id = id;
         this.name = name;
         this.amount = amount;
@@ -202,6 +210,8 @@ public class ChargeData implements Comparable<ChargeData>, 
Serializable {
         this.feeFrequencyOptions = feeFrequencyOptions;
         this.incomeOrLiabilityAccount = account;
         this.incomeOrLiabilityAccountOptions = incomeOrLiabilityAccountOptions;
+        this.taxGroup = taxGroupData;
+        this.taxGroupOptions = taxGroupOptions;
     }
 
     @Override
@@ -249,9 +259,9 @@ public class ChargeData implements Comparable<ChargeData>, 
Serializable {
         final LocalDate inactivationDate = null;
 
         return SavingsAccountChargeData.instance(savingsChargeId, this.id, 
savingsAccountId, this.name, this.currency, this.amount,
-                amountPaid, amountWaived, amountWrittenOff, amountOutstanding, 
this.chargeTimeType, dueAsOfDate, this.chargeCalculationType,
-                percentage, amountPercentageAppliedTo, chargeOptions, 
this.penalty, this.feeOnMonthDay, this.feeInterval, isActive,
-                inactivationDate);
+                amountPaid, amountWaived, amountWrittenOff, amountOutstanding, 
this.chargeTimeType, dueAsOfDate,
+                this.chargeCalculationType, percentage, 
amountPercentageAppliedTo, chargeOptions, this.penalty, this.feeOnMonthDay,
+                this.feeInterval, isActive, inactivationDate);
     }
 
     public boolean isPenalty() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
index 7f8a161..3008849 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
@@ -49,6 +49,8 @@ import 
org.apache.fineract.portfolio.charge.exception.ChargeMustBePenaltyExcepti
 import 
org.apache.fineract.portfolio.charge.exception.ChargeParameterUpdateNotSupportedException;
 import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
+import org.apache.fineract.portfolio.tax.data.TaxGroupData;
+import org.apache.fineract.portfolio.tax.domain.TaxGroup;
 import org.joda.time.MonthDay;
 import org.springframework.data.jpa.domain.AbstractPersistable;
 
@@ -108,7 +110,11 @@ public class Charge extends AbstractPersistable<Long> {
     @JoinColumn(name = "income_or_liability_account_id")
     private GLAccount account;
 
-    public static Charge fromJson(final JsonCommand command, final GLAccount 
account) {
+    @ManyToOne
+    @JoinColumn(name = "tax_group_id")
+    private TaxGroup taxGroup;
+
+    public static Charge fromJson(final JsonCommand command, final GLAccount 
account, final TaxGroup taxGroup) {
 
         final String name = command.stringValueOfParameterNamed("name");
         final BigDecimal amount = 
command.bigDecimalValueOfParameterNamed("amount");
@@ -116,8 +122,8 @@ public class Charge extends AbstractPersistable<Long> {
 
         final ChargeAppliesTo chargeAppliesTo = 
ChargeAppliesTo.fromInt(command.integerValueOfParameterNamed("chargeAppliesTo"));
         final ChargeTimeType chargeTimeType = 
ChargeTimeType.fromInt(command.integerValueOfParameterNamed("chargeTimeType"));
-        final ChargeCalculationType chargeCalculationType = 
ChargeCalculationType
-                
.fromInt(command.integerValueOfParameterNamed("chargeCalculationType"));
+        final ChargeCalculationType chargeCalculationType = 
ChargeCalculationType.fromInt(command
+                .integerValueOfParameterNamed("chargeCalculationType"));
         final Integer chargePaymentMode = 
command.integerValueOfParameterNamed("chargePaymentMode");
 
         final ChargePaymentMode paymentMode = chargePaymentMode == null ? null 
: ChargePaymentMode.fromInt(chargePaymentMode);
@@ -131,7 +137,7 @@ public class Charge extends AbstractPersistable<Long> {
         final Integer feeFrequency = 
command.integerValueOfParameterNamed("feeFrequency");
 
         return new Charge(name, amount, currencyCode, chargeAppliesTo, 
chargeTimeType, chargeCalculationType, penalty, active, paymentMode,
-                feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, 
account);
+                feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, 
account, taxGroup);
     }
 
     protected Charge() {
@@ -139,9 +145,9 @@ public class Charge extends AbstractPersistable<Long> {
     }
 
     private Charge(final String name, final BigDecimal amount, final String 
currencyCode, final ChargeAppliesTo chargeAppliesTo,
-            final ChargeTimeType chargeTime, final ChargeCalculationType 
chargeCalculationType, final boolean penalty, final boolean active,
-            final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, 
final Integer feeInterval, final BigDecimal minCap,
-            final BigDecimal maxCap, final Integer feeFrequency, final 
GLAccount account) {
+            final ChargeTimeType chargeTime, final ChargeCalculationType 
chargeCalculationType, final boolean penalty,
+            final boolean active, final ChargePaymentMode paymentMode, final 
MonthDay feeOnMonthDay, final Integer feeInterval,
+            final BigDecimal minCap, final BigDecimal maxCap, final Integer 
feeFrequency, final GLAccount account, final TaxGroup taxGroup) {
         this.name = name;
         this.amount = amount;
         this.currencyCode = currencyCode;
@@ -151,6 +157,7 @@ public class Charge extends AbstractPersistable<Long> {
         this.penalty = penalty;
         this.active = active;
         this.account = account;
+        this.taxGroup = taxGroup;
         this.chargePaymentMode = paymentMode == null ? null : 
paymentMode.getValue();
 
         final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
@@ -185,8 +192,8 @@ public class Charge extends AbstractPersistable<Long> {
 
         } else if (isLoanCharge()) {
 
-            if (penalty && (chargeTime.isTimeOfDisbursement()
-                    || chargeTime.isTrancheDisbursement())) { throw new 
ChargeDueAtDisbursementCannotBePenaltyException(name); }
+            if (penalty && (chargeTime.isTimeOfDisbursement() || 
chargeTime.isTrancheDisbursement())) { throw new 
ChargeDueAtDisbursementCannotBePenaltyException(
+                    name); }
             if (!penalty && chargeTime.isOverdueInstallment()) { throw new 
ChargeMustBePenaltyException(name); }
             // TODO vishwas, this validation seems unnecessary as identical
             // validation is performed in the write service
@@ -487,16 +494,23 @@ public class Charge extends AbstractPersistable<Long> {
 
         }
 
-        if (this.penalty && ChargeTimeType.fromInt(this.chargeTimeType)
-                .isTimeOfDisbursement()) { throw new 
ChargeDueAtDisbursementCannotBePenaltyException(this.name); }
-        if (!penalty
-                && 
ChargeTimeType.fromInt(this.chargeTimeType).isOverdueInstallment()) { throw new 
ChargeMustBePenaltyException(name); }
+        if (this.penalty && 
ChargeTimeType.fromInt(this.chargeTimeType).isTimeOfDisbursement()) { throw new 
ChargeDueAtDisbursementCannotBePenaltyException(
+                this.name); }
+        if (!penalty && 
ChargeTimeType.fromInt(this.chargeTimeType).isOverdueInstallment()) { throw new 
ChargeMustBePenaltyException(name); }
 
         if 
(command.isChangeInLongParameterNamed(ChargesApiConstants.glAccountIdParamName, 
getIncomeAccountId())) {
             final Long newValue = 
command.longValueOfParameterNamed(ChargesApiConstants.glAccountIdParamName);
             actualChanges.put(ChargesApiConstants.glAccountIdParamName, 
newValue);
         }
 
+        if 
(command.isChangeInLongParameterNamed(ChargesApiConstants.taxGroupIdParamName, 
getTaxGroupId())) {
+            final Long newValue = 
command.longValueOfParameterNamed(ChargesApiConstants.taxGroupIdParamName);
+            actualChanges.put(ChargesApiConstants.taxGroupIdParamName, 
newValue);
+            if(taxGroup != null){
+                
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).failWithCode("modification.not.supported");
+            }
+        }
+
         if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
 
         return actualChanges;
@@ -524,10 +538,15 @@ public class Charge extends AbstractPersistable<Long> {
         if (account != null) {
             accountData = new GLAccountData(account.getId(), 
account.getName(), account.getGlCode());
         }
+        TaxGroupData taxGroupData = null;
+        if (this.taxGroup != null) {
+            taxGroupData = TaxGroupData.lookup(taxGroup.getId(), 
taxGroup.getName());
+        }
+
         final CurrencyData currency = new CurrencyData(this.currencyCode, 
null, 0, 0, null, null);
         return ChargeData.instance(getId(), this.name, this.amount, currency, 
chargeTimeType, chargeAppliesTo, chargeCalculationType,
                 chargePaymentmode, getFeeOnMonthDay(), this.feeInterval, 
this.penalty, this.active, this.minCap, this.maxCap,
-                feeFrequencyType, accountData);
+                feeFrequencyType, accountData, taxGroupData);
     }
 
     public Integer getChargePaymentMode() {
@@ -582,8 +601,24 @@ public class Charge extends AbstractPersistable<Long> {
         return incomeAccountId;
     }
 
+    private Long getTaxGroupId() {
+        Long taxGroupId = null;
+        if (this.taxGroup != null) {
+            taxGroupId = this.taxGroup.getId();
+        }
+        return taxGroupId;
+    }
+
     public boolean isDisbursementCharge() {
         return 
ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.DISBURSEMENT)
                 || 
ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.TRANCHE_DISBURSEMENT);
     }
+
+    public TaxGroup getTaxGroup() {
+        return this.taxGroup;
+    }
+
+    public void setTaxGroup(TaxGroup taxGroup) {
+        this.taxGroup = taxGroup;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
index c8a90e4..bbf18ba 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java
@@ -56,7 +56,7 @@ public final class 
ChargeDefinitionCommandFromApiJsonDeserializer {
     private final Set<String> supportedParameters = new 
HashSet<>(Arrays.asList("name", "amount", "locale", "currencyCode",
             "currencyOptions", "chargeAppliesTo", "chargeTimeType", 
"chargeCalculationType", "chargeCalculationTypeOptions", "penalty",
             "active", "chargePaymentMode", "feeOnMonthDay", "feeInterval", 
"monthDayFormat", "minCap", "maxCap", "feeFrequency",
-            ChargesApiConstants.glAccountIdParamName));
+            ChargesApiConstants.glAccountIdParamName, 
ChargesApiConstants.taxGroupIdParamName));
 
     private final FromJsonHelper fromApiJsonHelper;
 
@@ -206,6 +206,11 @@ public final class 
ChargeDefinitionCommandFromApiJsonDeserializer {
             
baseDataValidator.reset().parameter("maxCap").value(maxCap).notNull().positiveAmount();
         }
 
+        if 
(this.fromApiJsonHelper.parameterExists(ChargesApiConstants.taxGroupIdParamName,
 element)) {
+            final Long taxGroupId = 
this.fromApiJsonHelper.extractLongNamed(ChargesApiConstants.taxGroupIdParamName,
 element);
+            
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).value(taxGroupId).notNull().longGreaterThanZero();
+        }
+
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
@@ -316,6 +321,11 @@ public final class 
ChargeDefinitionCommandFromApiJsonDeserializer {
                     .longGreaterThanZero();
         }
 
+        if 
(this.fromApiJsonHelper.parameterExists(ChargesApiConstants.taxGroupIdParamName,
 element)) {
+            final Long taxGroupId = 
this.fromApiJsonHelper.extractLongNamed(ChargesApiConstants.taxGroupIdParamName,
 element);
+            
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).value(taxGroupId).notNull().longGreaterThanZero();
+        }
+
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
index a1ae0bc..542e471 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java
@@ -41,6 +41,8 @@ import 
org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
 import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
 import org.apache.fineract.portfolio.common.service.CommonEnumerations;
 import 
org.apache.fineract.portfolio.common.service.DropdownReadPlatformService;
+import org.apache.fineract.portfolio.tax.data.TaxGroupData;
+import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService;
 import org.joda.time.MonthDay;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
@@ -64,12 +66,14 @@ public class ChargeReadPlatformServiceImpl implements 
ChargeReadPlatformService
     private final FineractEntityAccessUtil fineractEntityAccessUtil;
     private final AccountingDropdownReadPlatformService 
accountingDropdownReadPlatformService;
     private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+    private final TaxReadPlatformService taxReadPlatformService;
 
     @Autowired
     public ChargeReadPlatformServiceImpl(final CurrencyReadPlatformService 
currencyReadPlatformService,
             final ChargeDropdownReadPlatformService 
chargeDropdownReadPlatformService, final RoutingDataSource dataSource,
             final DropdownReadPlatformService dropdownReadPlatformService, 
final FineractEntityAccessUtil fineractEntityAccessUtil,
-            final AccountingDropdownReadPlatformService 
accountingDropdownReadPlatformService) {
+            final AccountingDropdownReadPlatformService 
accountingDropdownReadPlatformService,
+            final TaxReadPlatformService taxReadPlatformService) {
         this.chargeDropdownReadPlatformService = 
chargeDropdownReadPlatformService;
         this.jdbcTemplate = new JdbcTemplate(dataSource);
         this.currencyReadPlatformService = currencyReadPlatformService;
@@ -77,6 +81,7 @@ public class ChargeReadPlatformServiceImpl implements 
ChargeReadPlatformService
         this.fineractEntityAccessUtil = fineractEntityAccessUtil;
         this.accountingDropdownReadPlatformService = 
accountingDropdownReadPlatformService;
         this.namedParameterJdbcTemplate = new 
NamedParameterJdbcTemplate(dataSource);
+        this.taxReadPlatformService = taxReadPlatformService;
     }
 
     @Override
@@ -142,11 +147,11 @@ public class ChargeReadPlatformServiceImpl implements 
ChargeReadPlatformService
         final List<EnumOptionData> feeFrequencyOptions = 
this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
         final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions 
= this.accountingDropdownReadPlatformService
                 .retrieveAccountMappingOptionsForCharges();
-
+        final Collection<TaxGroupData> taxGroupOptions = 
this.taxReadPlatformService.retrieveTaxGroupsForLookUp();
         return ChargeData.template(currencyOptions, 
allowedChargeCalculationTypeOptions, allowedChargeAppliesToOptions,
                 allowedChargeTimeOptions, chargePaymentOptions, 
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
                 savingsChargeCalculationTypeOptions, 
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
-                clientChargeTimeTypeOptions, feeFrequencyOptions, 
incomeOrLiabilityAccountOptions);
+                clientChargeTimeTypeOptions, feeFrequencyOptions, 
incomeOrLiabilityAccountOptions, taxGroupOptions);
     }
 
     @Override
@@ -252,7 +257,8 @@ public class ChargeReadPlatformServiceImpl implements 
ChargeReadPlatformService
 
         // Check if branch specific products are enabled. If yes, fetch only
         // charges mapped to current user's office
-        String inClause = 
fineractEntityAccessUtil.getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(FineractEntityType.CHARGE);
+        String inClause = fineractEntityAccessUtil
+                
.getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(FineractEntityType.CHARGE);
         if ((inClause != null) && (!(inClause.trim().isEmpty()))) {
             sql += " and c.id in ( " + inClause + " ) ";
         }
@@ -271,9 +277,11 @@ public class ChargeReadPlatformServiceImpl implements 
ChargeReadPlatformService
                     + "oc.currency_multiplesof as inMultiplesOf, 
oc.display_symbol as currencyDisplaySymbol, "
                     + "oc.internationalized_name_code as currencyNameCode, 
c.fee_on_day as feeOnDay, c.fee_on_month as feeOnMonth, "
                     + "c.fee_interval as feeInterval, c.fee_frequency as 
feeFrequency,c.min_cap as minCap,c.max_cap as maxCap, "
-                    + "c.income_or_liability_account_id as glAccountId , 
acc.name as glAccountName, acc.gl_code as glCode "
-                    + "from m_charge c " + "join m_organisation_currency oc on 
c.currency_code = oc.code "
-                    + " LEFT JOIN acc_gl_account acc on acc.id = 
c.income_or_liability_account_id ";
+                    + "c.income_or_liability_account_id as glAccountId , 
acc.name as glAccountName, acc.gl_code as glCode, "
+                    + "tg.id as taxGroupId, tg.name as taxGroupName " + "from 
m_charge c "
+                    + "join m_organisation_currency oc on c.currency_code = 
oc.code "
+                    + " LEFT JOIN acc_gl_account acc on acc.id = 
c.income_or_liability_account_id "
+                    + " LEFT JOIN m_tax_group tg on tg.id = c.tax_group_id ";
         }
 
         public String loanProductChargeSchema() {
@@ -339,8 +347,16 @@ public class ChargeReadPlatformServiceImpl implements 
ChargeReadPlatformService
                 glAccountData = new GLAccountData(glAccountId, glAccountName, 
glCode);
             }
 
+            final Long taxGroupId = JdbcSupport.getLong(rs, "taxGroupId");
+            final String taxGroupName = rs.getString("taxGroupName");
+            TaxGroupData taxGroupData = null;
+            if (taxGroupId != null) {
+                taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
+            }
+
             return ChargeData.instance(id, name, amount, currency, 
chargeTimeType, chargeAppliesToType, chargeCalculationType,
-                    chargePaymentMode, feeOnMonthDay, feeInterval, penalty, 
active, minCap, maxCap, feeFrequencyType, glAccountData);
+                    chargePaymentMode, feeOnMonthDay, feeInterval, penalty, 
active, minCap, maxCap, feeFrequencyType, glAccountData,
+                    taxGroupData);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
index 3327701..35e5420 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java
@@ -43,6 +43,8 @@ import 
org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
 import 
org.apache.fineract.portfolio.charge.serialization.ChargeDefinitionCommandFromApiJsonDeserializer;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
+import org.apache.fineract.portfolio.tax.domain.TaxGroup;
+import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -64,12 +66,14 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
     private final LoanProductRepository loanProductRepository;
     private final FineractEntityAccessUtil fineractEntityAccessUtil;
     private final GLAccountRepositoryWrapper gLAccountRepository;
+    private final TaxGroupRepositoryWrapper taxGroupRepository;
 
     @Autowired
     public ChargeWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
             final ChargeDefinitionCommandFromApiJsonDeserializer 
fromApiJsonDeserializer, final ChargeRepository chargeRepository,
             final LoanProductRepository loanProductRepository, final 
RoutingDataSource dataSource,
-            final FineractEntityAccessUtil fineractEntityAccessUtil, final 
GLAccountRepositoryWrapper glAccountRepository) {
+            final FineractEntityAccessUtil fineractEntityAccessUtil, final 
GLAccountRepositoryWrapper glAccountRepository,
+            final TaxGroupRepositoryWrapper taxGroupRepository) {
         this.context = context;
         this.fromApiJsonDeserializer = fromApiJsonDeserializer;
         this.dataSource = dataSource;
@@ -78,6 +82,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
         this.loanProductRepository = loanProductRepository;
         this.fineractEntityAccessUtil = fineractEntityAccessUtil;
         this.gLAccountRepository = glAccountRepository;
+        this.taxGroupRepository = taxGroupRepository;
     }
 
     @Transactional
@@ -96,14 +101,20 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
                 glAccount = 
this.gLAccountRepository.findOneWithNotFoundDetection(glAccountId);
             }
 
-            final Charge charge = Charge.fromJson(command, glAccount);
+            final Long taxGroupId = 
command.longValueOfParameterNamed(ChargesApiConstants.taxGroupIdParamName);
+            TaxGroup taxGroup = null;
+            if (taxGroupId != null) {
+                taxGroup = 
this.taxGroupRepository.findOneWithNotFoundDetection(taxGroupId);
+            }
+
+            final Charge charge = Charge.fromJson(command, glAccount, 
taxGroup);
             this.chargeRepository.save(charge);
 
             // check if the office specific products are enabled. If yes, then
             // save this savings product against a specific office
             // i.e. this savings product is specific for this office.
-            
fineractEntityAccessUtil.checkConfigurationAndAddProductResrictionsForUserOffice(FineractEntityAccessType.OFFICE_ACCESS_TO_CHARGES,
-                    FineractEntityType.CHARGE, charge.getId());
+            
fineractEntityAccessUtil.checkConfigurationAndAddProductResrictionsForUserOffice(
+                    FineractEntityAccessType.OFFICE_ACCESS_TO_CHARGES, 
FineractEntityType.CHARGE, charge.getId());
 
             return new 
CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(charge.getId()).build();
         } catch (final DataIntegrityViolationException dve) {
@@ -126,7 +137,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
             final Map<String, Object> changes = 
chargeForUpdate.update(command);
 
             
this.fromApiJsonDeserializer.validateChargeTimeNCalculationType(chargeForUpdate.getChargeTimeType(),
-                                                                               
                                                                
chargeForUpdate.getChargeCalculation());
+                    chargeForUpdate.getChargeCalculation());
 
             // MIFOSX-900: Check if the Charge has been active before and now 
is
             // deactivated:
@@ -146,7 +157,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
                 if (isChargeExistWithLoans) { throw new 
ChargeCannotBeUpdatedException(
                         
"error.msg.charge.frequency.cannot.be.updated.it.is.used.in.loan",
                         "This charge frequency cannot be updated, it is used 
in loan"); }
-            } 
+            }
 
             // Has account Id been changed ?
             if (changes.containsKey(ChargesApiConstants.glAccountIdParamName)) 
{
@@ -158,6 +169,15 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
                 chargeForUpdate.setAccount(newIncomeAccount);
             }
 
+            if (changes.containsKey(ChargesApiConstants.taxGroupIdParamName)) {
+                final Long newValue = 
command.longValueOfParameterNamed(ChargesApiConstants.taxGroupIdParamName);
+                TaxGroup taxGroup = null;
+                if (newValue != null) {
+                    taxGroup = 
this.taxGroupRepository.findOneWithNotFoundDetection(newValue);
+                }
+                chargeForUpdate.setTaxGroup(taxGroup);
+            }
+
             if (!changes.isEmpty()) {
                 this.chargeRepository.save(chargeForUpdate);
             }
@@ -182,10 +202,9 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl 
implements ChargeWriteP
         final Boolean isChargeExistWithSavings = 
isAnySavingsAssociateWithThisCharge(chargeId);
 
         // TODO: Change error messages around:
-        if (!loanProducts.isEmpty() || isChargeExistWithLoans
-                || isChargeExistWithSavings) { throw new 
ChargeCannotBeDeletedException(
-                        
"error.msg.charge.cannot.be.deleted.it.is.already.used.in.loan",
-                        "This charge cannot be deleted, it is already used in 
loan"); }
+        if (!loanProducts.isEmpty() || isChargeExistWithLoans || 
isChargeExistWithSavings) { throw new ChargeCannotBeDeletedException(
+                
"error.msg.charge.cannot.be.deleted.it.is.already.used.in.loan",
+                "This charge cannot be deleted, it is already used in loan"); }
 
         chargeForDelete.delete();
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java
index f38d87e..0c80ce3 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java
@@ -41,6 +41,7 @@ import 
org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
 import 
org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
+import org.apache.fineract.portfolio.tax.data.TaxGroupData;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -156,11 +157,12 @@ public class LoanChargeReadPlatformServiceImpl implements 
LoanChargeReadPlatform
         final List<EnumOptionData> feeFrequencyOptions = 
this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
         // this field is applicable only for client charges
         final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions 
= null;
+        final Collection<TaxGroupData> taxGroupOptions = null;
 
         return ChargeData.template(null, allowedChargeCalculationTypeOptions, 
null, allowedChargeTimeOptions, null,
                 loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, 
savingsChargeCalculationTypeOptions,
                 savingsChargeTimeTypeOptions, 
clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, 
feeFrequencyOptions,
-                incomeOrLiabilityAccountOptions);
+                incomeOrLiabilityAccountOptions, taxGroupOptions);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
index e2ebfa2..7bebd27 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
@@ -217,7 +217,8 @@ public class DepositsApiConstants {
             SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), 
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(),
             SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(),
             
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(),
-            
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(), 
chartsParamName));
+            
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(), 
chartsParamName,
+            SavingsApiConstants.withHoldTaxParamName, 
SavingsApiConstants.taxGroupIdParamName));
 
     private static final Set<String> PRECLOSURE_REQUEST_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(preClosurePenalApplicableParamName,
             preClosurePenalInterestParamName, 
preClosurePenalInterestOnTypeIdParamName));
@@ -298,7 +299,7 @@ public class DepositsApiConstants {
             interestCompoundingPeriodTypeParamName, 
interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
             interestCalculationDaysInYearTypeParamName, 
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
             chargesParamName, chartsParamName, depositAmountParamName, 
depositPeriodParamName, depositPeriodFrequencyIdParamName,
-            savingsAccounts, expectedFirstDepositOnDateParamName));
+            savingsAccounts, expectedFirstDepositOnDateParamName, 
SavingsApiConstants.withHoldTaxParamName));
 
     public static final Set<String> 
FIXED_DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS = 
fixedDepositAccountRequestData();
     public static final Set<String> 
FIXED_DEPOSIT_ACCOUNT_RESPONSE_DATA_PARAMETERS = 
fixedDepositAccountResponseData();

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsAccountTransactionType.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsAccountTransactionType.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsAccountTransactionType.java
index 6ff57f7..f326b08 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsAccountTransactionType.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsAccountTransactionType.java
@@ -38,7 +38,8 @@ public enum SavingsAccountTransactionType {
     APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
     WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
     REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"), 
WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), //
-    OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"); 
//
+    OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"), 
//
+    WITHHOLD_TAX(18, "savingsAccountTransactionType.withholdTax");
 
     private final Integer value;
     private final String code;
@@ -101,6 +102,9 @@ public enum SavingsAccountTransactionType {
             case 17:
                 savingsAccountTransactionType = 
SavingsAccountTransactionType.OVERDRAFT_INTEREST;
             break;
+            case 18:
+                savingsAccountTransactionType = 
SavingsAccountTransactionType.WITHHOLD_TAX;
+            break;
         }
         return savingsAccountTransactionType;
     }
@@ -117,6 +121,10 @@ public enum SavingsAccountTransactionType {
         return 
this.value.equals(SavingsAccountTransactionType.INTEREST_POSTING.getValue());
     }
 
+    public boolean isWithHoldTax() {
+        return 
this.value.equals(SavingsAccountTransactionType.WITHHOLD_TAX.getValue());
+    }
+
     public boolean isWithdrawalFee() {
         return 
this.value.equals(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue());
     }
@@ -162,7 +170,7 @@ public enum SavingsAccountTransactionType {
     }
 
     public boolean isDebit() {
-        return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || 
isPayCharge() || isIncomeFromInterest();
+        return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || 
isPayCharge() || isIncomeFromInterest() || isWithHoldTax();
     }
 
     public boolean isCredit() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
index 7648b61..e269a54 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
@@ -117,6 +117,8 @@ public class SavingsApiConstants {
     public static final String minBalanceForInterestCalculationParamName = 
"minBalanceForInterestCalculation";
     public static final String withdrawBalanceParamName = "withdrawBalance";
     public static final String onHoldFundsParamName = "onHoldFunds";
+    public static final String withHoldTaxParamName = "withHoldTax";
+    public static final String taxGroupIdParamName = "taxGroupId";
 
     // transaction parameters
     public static final String transactionDateParamName = "transactionDate";
@@ -177,8 +179,8 @@ public class SavingsApiConstants {
             
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
             SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
             SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), 
allowOverdraftParamName, overdraftLimitParamName,
-            nominalAnnualInterestRateOverdraftParamName, 
minOverdraftForInterestCalculationParamName,
-            minRequiredBalanceParamName, enforceMinRequiredBalanceParamName, 
minBalanceForInterestCalculationParamName));
+            nominalAnnualInterestRateOverdraftParamName, 
minOverdraftForInterestCalculationParamName, minRequiredBalanceParamName,
+            enforceMinRequiredBalanceParamName, 
minBalanceForInterestCalculationParamName, withHoldTaxParamName, 
taxGroupIdParamName));
 
     /**
      * These parameters will match the class level parameters of
@@ -193,18 +195,20 @@ public class SavingsApiConstants {
             withdrawalFeeForTransfersParamName, feeAmountParamName, 
feeOnMonthDayParamName, "currencyOptions",
             "interestCompoundingPeriodTypeOptions", 
"interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
             "interestCalculationDaysInYearTypeOptions", 
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions",
-            nominalAnnualInterestRateOverdraftParamName, 
minOverdraftForInterestCalculationParamName));
+            nominalAnnualInterestRateOverdraftParamName, 
minOverdraftForInterestCalculationParamName, withHoldTaxParamName,
+            taxGroupIdParamName));
 
     public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = 
new HashSet<>(Arrays.asList(localeParamName,
             dateFormatParamName, monthDayFormatParamName, staffIdParamName, 
accountNoParamName, externalIdParamName, clientIdParamName,
             groupIdParamName, productIdParamName, fieldOfficerIdParamName, 
submittedOnDateParamName, nominalAnnualInterestRateParamName,
             interestCompoundingPeriodTypeParamName, 
interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
-            interestCalculationDaysInYearTypeParamName, 
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
+            interestCalculationDaysInYearTypeParamName, 
minRequiredOpeningBalanceParamName,
+            lockinPeriodFrequencyParamName,
             lockinPeriodFrequencyTypeParamName,
             // withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
             withdrawalFeeForTransfersParamName, feeAmountParamName, 
feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName,
             overdraftLimitParamName, minRequiredBalanceParamName, 
enforceMinRequiredBalanceParamName,
-            nominalAnnualInterestRateOverdraftParamName, 
minOverdraftForInterestCalculationParamName));
+            nominalAnnualInterestRateOverdraftParamName, 
minOverdraftForInterestCalculationParamName, withHoldTaxParamName));
 
     /**
      * These parameters will match the class level parameters of

Reply via email to