fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@apache.org
Subject [14/51] [partial] incubator-fineract git commit: initial code push
Date Thu, 28 Jan 2016 05:46:59 GMT
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
new file mode 100644
index 0000000..c27abc3
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -0,0 +1,5051 @@
+/**
+ * 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.integrationtests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.accounting.Account;
+import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
+import org.apache.fineract.integrationtests.common.accounting.JournalEntry;
+import org.apache.fineract.integrationtests.common.accounting.JournalEntryHelper;
+import org.apache.fineract.integrationtests.common.accounting.PeriodicAccrualAccountingHelper;
+import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
+import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.integrationtests.common.savings.AccountTransferHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsStatusChecker;
+import org.joda.time.LocalDate;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.gson.JsonObject;
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.path.json.JsonPath;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+/**
+ * Client Loan Integration Test for checking Loan Application Repayments
+ * Schedule, loan charges, penalties, loan repayments and verifying accounting
+ * transactions
+ */
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public class ClientLoanIntegrationTest {
+
+    public static final String MINIMUM_OPENING_BALANCE = "1000.0";
+    public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
+
+    private static final String NONE = "1";
+    private static final String CASH_BASED = "2";
+    private static final String ACCRUAL_PERIODIC = "3";
+    private static final String ACCRUAL_UPFRONT = "4";
+
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private JournalEntryHelper journalEntryHelper;
+    private AccountHelper accountHelper;
+    private SchedulerJobHelper schedulerJobHelper;
+    private PeriodicAccrualAccountingHelper periodicAccrualAccountingHelper;
+    private SavingsAccountHelper savingsAccountHelper;
+    private AccountTransferHelper accountTransferHelper;
+
+    @Before
+    public void setup() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+        this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
+    }
+
+    @Test
+    public void checkClientLoanCreateAndDisburseFlow() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(false, NONE);
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00");
+        final ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec,
+                loanID);
+        verifyLoanRepaymentSchedule(loanSchedule);
+
+    }
+
+    @Test
+    public void testLoanCharges_DISBURSEMENT_FEE() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(false, NONE);
+
+        List<HashMap> charges = new ArrayList<>();
+        Integer flatDisbursement = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper.getLoanDisbursementJSON());
+
+        Integer amountPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, "1"));
+        addCharges(charges, amountPercentage, "1", null);
+        Integer amountPlusInterestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1"));
+        addCharges(charges, amountPlusInterestPercentage, "1", null);
+        Integer interestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1"));
+        addCharges(charges, interestPercentage, "1", null);
+
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        HashMap disbursementDetail = loanSchedule.get(0);
+
+        List<HashMap> loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+        validateCharge(amountPercentage, loanCharges, "1.0", "120.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "1.0", "6.06", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "126.06", "0.0", "0.0");
+
+        validateNumberForEqual("252.12", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getDisbursementChargesForLoanAsJSON(String.valueOf(flatDisbursement)));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+
+        validateCharge(flatDisbursement, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("352.12", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(amountPercentage, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(interestPercentage, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(amountPlusInterestPercentage, loanCharges)
+                .get("id"), LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(flatDisbursement, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("150"));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+        validateCharge(amountPercentage, loanCharges, "2.0", "240.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "2.0", "12.12", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "2.0", "252.12", "0.0", "0.0");
+        validateCharge(flatDisbursement, loanCharges, "150.0", "150.0", "0.0", "0.0");
+        validateNumberForEqual("654.24", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        this.loanTransactionHelper.updateLoan(loanID,
+                updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+        validateCharge(amountPercentage, loanCharges, "2.0", "200.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "2.0", "10.1", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "2.0", "210.1", "0.0", "0.0");
+        validateCharge(flatDisbursement, loanCharges, "150.0", "150.0", "0.0", "0.0");
+        validateNumberForEqual("570.2", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        this.loanTransactionHelper.updateLoan(loanID,
+                updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flatDisbursement, "1"), null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+        validateCharge(amountPercentage, loanCharges, "1.0", "100.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "1.0", "5.05", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "105.05", "0.0", "0.0");
+        validateNumberForEqual("210.1", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        charges.clear();
+        addCharges(charges, flatDisbursement, "100", null);
+        this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+        validateCharge(flatDisbursement, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("100.0", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        this.loanTransactionHelper.deleteChargesForLoan(loanID, (Integer) getloanCharge(flatDisbursement, loanCharges).get("id"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+        Assert.assertEquals(0, loanCharges.size());
+        validateNumberForEqual("0.0", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+    }
+
+    @Test
+    public void testLoanCharges_DISBURSEMENT_FEE_WITH_AMOUNT_CHANGE() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(false, NONE);
+
+        List<HashMap> charges = new ArrayList<>();
+        Integer amountPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, "1"));
+        addCharges(charges, amountPercentage, "1", null);
+        Integer amountPlusInterestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1"));
+        addCharges(charges, amountPlusInterestPercentage, "1", null);
+        Integer interestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1"));
+        addCharges(charges, interestPercentage, "1", null);
+
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        HashMap disbursementDetail = loanSchedule.get(0);
+
+        List<HashMap> loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+        validateCharge(amountPercentage, loanCharges, "1.0", "120.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "1.0", "6.06", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "126.06", "0.0", "0.0");
+        validateNumberForEqual("252.12", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        // DISBURSE
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID, "10000");
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        disbursementDetail = loanSchedule.get(0);
+
+        validateCharge(amountPercentage, loanCharges, "1.0", "0.0", "100.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "1.0", "0.0", "5.05", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "0.0", "105.05", "0.0");
+        validateNumberForEqual("210.1", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+    }
+
+    @Test
+    public void testLoanCharges_SPECIFIED_DUE_DATE_FEE() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(false, NONE);
+
+        List<HashMap> charges = new ArrayList<>();
+        Integer flat = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", false));
+        Integer flatAccTransfer = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanSpecifiedDueDateWithAccountTransferJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", false));
+
+        Integer amountPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, "1", false));
+        addCharges(charges, amountPercentage, "1", "29 September 2011");
+        Integer amountPlusInterestPercentage = ChargesHelper
+                .createCharges(requestSpec, responseSpec, ChargesHelper.getLoanSpecifiedDueDateJSON(
+                        ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1", false));
+        addCharges(charges, amountPlusInterestPercentage, "1", "29 September 2011");
+        Integer interestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false));
+        addCharges(charges, interestPercentage, "1", "29 September 2011");
+
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        HashMap firstInstallment = loanSchedule.get(1);
+
+        List<HashMap> loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+        validateCharge(amountPercentage, loanCharges, "1.0", "120.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "1.0", "6.06", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "126.06", "0.0", "0.0");
+
+        validateNumberForEqual("252.12", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(flat), "29 September 2011", "100"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+
+        validateCharge(flat, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("352.12", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(amountPercentage, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(interestPercentage, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(amountPlusInterestPercentage, loanCharges)
+                .get("id"), LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(flat, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("150"));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(amountPercentage, loanCharges, "2.0", "240.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "2.0", "12.12", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "2.0", "252.12", "0.0", "0.0");
+        validateCharge(flat, loanCharges, "150.0", "150.0", "0.0", "0.0");
+        validateNumberForEqual("654.24", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
+                MINIMUM_OPENING_BALANCE);
+        this.loanTransactionHelper.updateLoan(loanID,
+                updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), String.valueOf(savingsId)));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(amountPercentage, loanCharges, "2.0", "200.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "2.0", "10.1", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "2.0", "210.1", "0.0", "0.0");
+        validateCharge(flat, loanCharges, "150.0", "150.0", "0.0", "0.0");
+        validateNumberForEqual("570.2", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        this.loanTransactionHelper.updateLoan(loanID,
+                updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(amountPercentage, loanCharges, "1.0", "100.0", "0.0", "0.0");
+        validateCharge(interestPercentage, loanCharges, "1.0", "5.05", "0.0", "0.0");
+        validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "105.05", "0.0", "0.0");
+        validateNumberForEqual("210.1", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        charges.clear();
+        addCharges(charges, flat, "100", "29 September 2011");
+        this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(flat, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("100.0", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        this.loanTransactionHelper.deleteChargesForLoan(loanID, (Integer) getloanCharge(flat, loanCharges).get("id"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        Assert.assertEquals(0, loanCharges.size());
+        validateNumberForEqual("0", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(flatAccTransfer), "29 September 2011", "100"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(flatAccTransfer, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("100.0", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        // DISBURSE
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(amountPercentage), "29 September 2011", "1"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(amountPercentage, loanCharges, "1.0", "100.0", "0.0", "0.0");
+        validateCharge(flatAccTransfer, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("200.0", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        this.loanTransactionHelper.waiveChargesForLoan(loanID, (Integer) getloanCharge(amountPercentage, loanCharges).get("id"), "");
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(amountPercentage, loanCharges, "1.0", "0.0", "0.0", "100.0");
+        validateCharge(flatAccTransfer, loanCharges, "100.0", "100.0", "0.0", "0.0");
+        validateNumberForEqual("200.0", String.valueOf(firstInstallment.get("feeChargesDue")));
+        validateNumberForEqual("100.0", String.valueOf(firstInstallment.get("feeChargesOutstanding")));
+        validateNumberForEqual("100.0", String.valueOf(firstInstallment.get("feeChargesWaived")));
+
+        this.loanTransactionHelper.payChargesForLoan(loanID, (Integer) getloanCharge(flatAccTransfer, loanCharges).get("id"),
+                LoanTransactionHelper.getPayChargeJSON(SavingsAccountHelper.TRANSACTION_DATE, null));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        firstInstallment = loanSchedule.get(1);
+        validateCharge(amountPercentage, loanCharges, "1.0", "0.0", "0.0", "100.0");
+        validateCharge(flatAccTransfer, loanCharges, "100.0", "0.0", "100.0", "0.0");
+        validateNumberForEqual("200.0", String.valueOf(firstInstallment.get("feeChargesDue")));
+        validateNumberForEqual("100.0", String.valueOf(firstInstallment.get("feeChargesWaived")));
+        validateNumberForEqual("100.0", String.valueOf(firstInstallment.get("feeChargesPaid")));
+        validateNumberForEqual("0.0", String.valueOf(firstInstallment.get("feeChargesOutstanding")));
+    }
+
+    @Test
+    public void testLoanCharges_INSTALMENT_FEE() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(false, NONE);
+
+        List<HashMap> charges = new ArrayList<>();
+        Integer flat = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
+        Integer flatAccTransfer = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanInstallmentWithAccountTransferJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
+
+        Integer amountPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, "1", false));
+        addCharges(charges, amountPercentage, "1", "29 September 2011");
+        Integer amountPlusInterestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1", false));
+        addCharges(charges, amountPlusInterestPercentage, "1", "29 September 2011");
+        Integer interestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false));
+        addCharges(charges, interestPercentage, "1", "29 September 2011");
+
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        List<HashMap> loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+        Float totalPerOfAmout = 0F;
+        Float totalPerOfAmoutPlusInt = 0F;
+        Float totalPerOfint = 0F;
+        for (HashMap installment : loanSchedule) {
+            Float principalDue = (Float) installment.get("principalDue");
+            Float interestDue = (Float) installment.get("interestDue");
+            Float principalFee = principalDue / 100;
+            Float interestFee = interestDue / 100;
+            Float totalInstallmentFee = (principalFee * 2) + (interestFee * 2);
+            validateNumberForEqualExcludePrecission(String.valueOf(totalInstallmentFee), String.valueOf(installment.get("feeChargesDue")));
+            totalPerOfAmout = totalPerOfAmout + principalFee;
+            totalPerOfAmoutPlusInt = totalPerOfAmoutPlusInt + principalFee + interestFee;
+            totalPerOfint = totalPerOfint + interestFee;
+        }
+
+        validateChargeExcludePrecission(amountPercentage, loanCharges, "1.0", String.valueOf(totalPerOfAmout), "0.0", "0.0");
+        validateChargeExcludePrecission(interestPercentage, loanCharges, "1.0", String.valueOf(totalPerOfint), "0.0", "0.0");
+        validateChargeExcludePrecission(amountPlusInterestPercentage, loanCharges, "1.0", String.valueOf(totalPerOfAmoutPlusInt), "0.0",
+                "0.0");
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getInstallmentChargesForLoanAsJSON(String.valueOf(flat), "50"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        totalPerOfAmout = 0F;
+        totalPerOfAmoutPlusInt = 0F;
+        totalPerOfint = 0F;
+        for (HashMap installment : loanSchedule) {
+            Float principalDue = (Float) installment.get("principalDue");
+            Float interestDue = (Float) installment.get("interestDue");
+            Float principalFee = principalDue / 100;
+            Float interestFee = interestDue / 100;
+            Float totalInstallmentFee = (principalFee * 2) + (interestFee * 2) + 50;
+            validateNumberForEqualExcludePrecission(String.valueOf(totalInstallmentFee), String.valueOf(installment.get("feeChargesDue")));
+            totalPerOfAmout = totalPerOfAmout + principalFee;
+            totalPerOfAmoutPlusInt = totalPerOfAmoutPlusInt + principalFee + interestFee;
+            totalPerOfint = totalPerOfint + interestFee;
+        }
+
+        validateChargeExcludePrecission(amountPercentage, loanCharges, "1.0", String.valueOf(totalPerOfAmout), "0.0", "0.0");
+        validateChargeExcludePrecission(interestPercentage, loanCharges, "1.0", String.valueOf(totalPerOfint), "0.0", "0.0");
+        validateChargeExcludePrecission(amountPlusInterestPercentage, loanCharges, "1.0", String.valueOf(totalPerOfAmoutPlusInt), "0.0",
+                "0.0");
+        validateChargeExcludePrecission(flat, loanCharges, "50.0", "200", "0.0", "0.0");
+
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(amountPercentage, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(interestPercentage, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(amountPlusInterestPercentage, loanCharges)
+                .get("id"), LoanTransactionHelper.getUpdateChargesForLoanAsJSON("2"));
+        this.loanTransactionHelper.updateChargesForLoan(loanID, (Integer) getloanCharge(flat, loanCharges).get("id"),
+                LoanTransactionHelper.getUpdateChargesForLoanAsJSON("100"));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        totalPerOfAmout = 0F;
+        totalPerOfAmoutPlusInt = 0F;
+        totalPerOfint = 0F;
+        for (HashMap installment : loanSchedule) {
+            Float principalDue = (Float) installment.get("principalDue");
+            Float interestDue = (Float) installment.get("interestDue");
+            Float principalFee = principalDue * 2 / 100;
+            Float interestFee = interestDue * 2 / 100;
+            Float totalInstallmentFee = (principalFee * 2) + (interestFee * 2) + 100;
+            validateNumberForEqualExcludePrecission(String.valueOf(totalInstallmentFee), String.valueOf(installment.get("feeChargesDue")));
+            totalPerOfAmout = totalPerOfAmout + principalFee;
+            totalPerOfAmoutPlusInt = totalPerOfAmoutPlusInt + principalFee + interestFee;
+            totalPerOfint = totalPerOfint + interestFee;
+        }
+
+        validateChargeExcludePrecission(amountPercentage, loanCharges, "2.0", String.valueOf(totalPerOfAmout), "0.0", "0.0");
+        validateChargeExcludePrecission(interestPercentage, loanCharges, "2.0", String.valueOf(totalPerOfint), "0.0", "0.0");
+        validateChargeExcludePrecission(amountPlusInterestPercentage, loanCharges, "2.0", String.valueOf(totalPerOfAmoutPlusInt), "0.0",
+                "0.0");
+        validateChargeExcludePrecission(flat, loanCharges, "100.0", "400", "0.0", "0.0");
+
+        final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
+                MINIMUM_OPENING_BALANCE);
+        this.loanTransactionHelper.updateLoan(loanID,
+                updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), String.valueOf(savingsId)));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        totalPerOfAmout = 0F;
+        totalPerOfAmoutPlusInt = 0F;
+        totalPerOfint = 0F;
+        for (HashMap installment : loanSchedule) {
+            Float principalDue = (Float) installment.get("principalDue");
+            Float interestDue = (Float) installment.get("interestDue");
+            Float principalFee = principalDue * 2 / 100;
+            Float interestFee = interestDue * 2 / 100;
+            Float totalInstallmentFee = (principalFee * 2) + (interestFee * 2) + 100;
+            validateNumberForEqualExcludePrecission(String.valueOf(totalInstallmentFee), String.valueOf(installment.get("feeChargesDue")));
+            totalPerOfAmout = totalPerOfAmout + principalFee;
+            totalPerOfAmoutPlusInt = totalPerOfAmoutPlusInt + principalFee + interestFee;
+            totalPerOfint = totalPerOfint + interestFee;
+        }
+
+        validateChargeExcludePrecission(amountPercentage, loanCharges, "2.0", String.valueOf(totalPerOfAmout), "0.0", "0.0");
+        validateChargeExcludePrecission(interestPercentage, loanCharges, "2.0", String.valueOf(totalPerOfint), "0.0", "0.0");
+        validateChargeExcludePrecission(amountPlusInterestPercentage, loanCharges, "2.0", String.valueOf(totalPerOfAmoutPlusInt), "0.0",
+                "0.0");
+        validateChargeExcludePrecission(flat, loanCharges, "100.0", "400", "0.0", "0.0");
+
+        this.loanTransactionHelper.updateLoan(loanID,
+                updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        totalPerOfAmout = 0F;
+        totalPerOfAmoutPlusInt = 0F;
+        totalPerOfint = 0F;
+        for (HashMap installment : loanSchedule) {
+            Float principalDue = (Float) installment.get("principalDue");
+            Float interestDue = (Float) installment.get("interestDue");
+            Float principalFee = principalDue / 100;
+            Float interestFee = interestDue / 100;
+            Float totalInstallmentFee = (principalFee * 2) + (interestFee * 2);
+            validateNumberForEqualExcludePrecission(String.valueOf(totalInstallmentFee), String.valueOf(installment.get("feeChargesDue")));
+            totalPerOfAmout = totalPerOfAmout + principalFee;
+            totalPerOfAmoutPlusInt = totalPerOfAmoutPlusInt + principalFee + interestFee;
+            totalPerOfint = totalPerOfint + interestFee;
+        }
+
+        validateChargeExcludePrecission(amountPercentage, loanCharges, "1.0", String.valueOf(totalPerOfAmout), "0.0", "0.0");
+        validateChargeExcludePrecission(interestPercentage, loanCharges, "1.0", String.valueOf(totalPerOfint), "0.0", "0.0");
+        validateChargeExcludePrecission(amountPlusInterestPercentage, loanCharges, "1.0", String.valueOf(totalPerOfAmoutPlusInt), "0.0",
+                "0.0");
+
+        charges.clear();
+        addCharges(charges, flat, "50", "29 September 2011");
+        this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        for (HashMap installment : loanSchedule) {
+            validateNumberForEqualExcludePrecission("50", String.valueOf(installment.get("feeChargesDue")));
+        }
+        validateChargeExcludePrecission(flat, loanCharges, "50.0", "200", "0.0", "0.0");
+
+        this.loanTransactionHelper.deleteChargesForLoan(loanID, (Integer) getloanCharge(flat, loanCharges).get("id"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        for (HashMap installment : loanSchedule) {
+            validateNumberForEqualExcludePrecission("0", String.valueOf(installment.get("feeChargesDue")));
+        }
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getInstallmentChargesForLoanAsJSON(String.valueOf(flatAccTransfer), "100"));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        for (HashMap installment : loanSchedule) {
+            validateNumberForEqualExcludePrecission("100", String.valueOf(installment.get("feeChargesDue")));
+        }
+        validateChargeExcludePrecission(flatAccTransfer, loanCharges, "100.0", "400", "0.0", "0.0");
+
+        // DISBURSE
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        this.loanTransactionHelper.addChargesForLoan(loanID,
+                LoanTransactionHelper.getInstallmentChargesForLoanAsJSON(String.valueOf(flat), "50"));
+
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        for (HashMap installment : loanSchedule) {
+            validateNumberForEqualExcludePrecission("150", String.valueOf(installment.get("feeChargesDue")));
+        }
+        validateChargeExcludePrecission(flatAccTransfer, loanCharges, "100.0", "400", "0.0", "0.0");
+        validateChargeExcludePrecission(flat, loanCharges, "50.0", "200", "0.0", "0.0");
+
+        Integer waivePeriodnum = 1;
+        this.loanTransactionHelper.waiveChargesForLoan(loanID, (Integer) getloanCharge(flat, loanCharges).get("id"),
+                LoanTransactionHelper.getWaiveChargeJSON(String.valueOf(waivePeriodnum)));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        for (HashMap installment : loanSchedule) {
+            validateNumberForEqualExcludePrecission("150", String.valueOf(installment.get("feeChargesDue")));
+            if (waivePeriodnum == installment.get("period")) {
+                validateNumberForEqualExcludePrecission("100.0", String.valueOf(installment.get("feeChargesOutstanding")));
+                validateNumberForEqualExcludePrecission("50.0", String.valueOf(installment.get("feeChargesWaived")));
+            } else {
+                validateNumberForEqualExcludePrecission("150.0", String.valueOf(installment.get("feeChargesOutstanding")));
+                validateNumberForEqualExcludePrecission("0.0", String.valueOf(installment.get("feeChargesWaived")));
+
+            }
+        }
+        validateChargeExcludePrecission(flatAccTransfer, loanCharges, "100.0", "400", "0.0", "0.0");
+        validateChargeExcludePrecission(flat, loanCharges, "50.0", "150", "0.0", "50.0");
+
+        Integer payPeriodnum = 2;
+        this.loanTransactionHelper.payChargesForLoan(loanID, (Integer) getloanCharge(flatAccTransfer, loanCharges).get("id"),
+                LoanTransactionHelper.getPayChargeJSON(SavingsAccountHelper.TRANSACTION_DATE, String.valueOf(payPeriodnum)));
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        loanSchedule.remove(0);
+        for (HashMap installment : loanSchedule) {
+            validateNumberForEqualExcludePrecission("150", String.valueOf(installment.get("feeChargesDue")));
+            if (payPeriodnum == installment.get("period")) {
+                validateNumberForEqualExcludePrecission("50.0", String.valueOf(installment.get("feeChargesOutstanding")));
+                validateNumberForEqualExcludePrecission("100.0", String.valueOf(installment.get("feeChargesPaid")));
+            } else if (waivePeriodnum == installment.get("period")) {
+                validateNumberForEqualExcludePrecission("100.0", String.valueOf(installment.get("feeChargesOutstanding")));
+                validateNumberForEqualExcludePrecission("50.0", String.valueOf(installment.get("feeChargesWaived")));
+            } else {
+                validateNumberForEqualExcludePrecission("150.0", String.valueOf(installment.get("feeChargesOutstanding")));
+                validateNumberForEqualExcludePrecission("0.0", String.valueOf(installment.get("feeChargesPaid")));
+
+            }
+        }
+        validateChargeExcludePrecission(flatAccTransfer, loanCharges, "100.0", "300", "100.0", "0.0");
+        validateChargeExcludePrecission(flat, loanCharges, "50.0", "150", "0.0", "50.0");
+
+    }
+
+    @Test
+    public void testLoanCharges_DISBURSEMENT_TO_SAVINGS() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        SavingsAccountHelper savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(false, NONE);
+
+        final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
+                MINIMUM_OPENING_BALANCE);
+
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, savingsId.toString(), "12,000.00");
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        HashMap summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        Float balance = new Float(MINIMUM_OPENING_BALANCE);
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+        // DISBURSE
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoanToSavings(SavingsAccountHelper.TRANSACTION_DATE, loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        balance = new Float(MINIMUM_OPENING_BALANCE) + new Float("12000");
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+        loanStatusHashMap = this.loanTransactionHelper.undoDisbursal(loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        balance = new Float(MINIMUM_OPENING_BALANCE);
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+    }
+
+    @Test
+    public void testLoanCharges_DISBURSEMENT_WITH_TRANCHES() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(true, NONE);
+
+        List<HashMap> tranches = new ArrayList<>();
+        tranches.add(createTrancheDetail("1 March 2014", "25000"));
+        tranches.add(createTrancheDetail("23 April 2014", "20000"));
+
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, null, "45,000.00", tranches);
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("1 March 2014", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        // DISBURSE first Tranche
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoan("1 March 2014", loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        // DISBURSE Second Tranche
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoan("23 April 2014", loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        loanStatusHashMap = this.loanTransactionHelper.undoDisbursal(loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+    }
+
+    @Test
+    public void testLoanCharges_DISBURSEMENT_TO_SAVINGS_WITH_TRANCHES() {
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        SavingsAccountHelper savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+        final Integer loanProductID = createLoanProduct(true, NONE);
+
+        final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID,
+                MINIMUM_OPENING_BALANCE);
+
+        List<HashMap> tranches = new ArrayList<>();
+        tranches.add(createTrancheDetail("1 March 2014", "25000"));
+        tranches.add(createTrancheDetail("23 April 2014", "20000"));
+
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, savingsId.toString(), "45,000.00",
+                tranches);
+        Assert.assertNotNull(loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("1 March 2014", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        HashMap summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        Float balance = new Float(MINIMUM_OPENING_BALANCE);
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+        // DISBURSE first Tranche
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoanToSavings("1 March 2014", loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        balance = new Float(MINIMUM_OPENING_BALANCE) + new Float("25000");
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+        // DISBURSE Second Tranche
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoanToSavings("23 April 2014", loanID);
+        System.out.println("DISBURSE " + loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        balance = new Float(MINIMUM_OPENING_BALANCE) + new Float("25000") + new Float("20000");
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+        loanStatusHashMap = this.loanTransactionHelper.undoDisbursal(loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        summary = savingsAccountHelper.getSavingsSummary(savingsId);
+        balance = new Float(MINIMUM_OPENING_BALANCE);
+        assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
+
+    }
+
+    private void validateCharge(Integer amountPercentage, final List<HashMap> loanCharges, final String amount, final String outstanding,
+            String amountPaid, String amountWaived) {
+        HashMap chargeDetail = getloanCharge(amountPercentage, loanCharges);
+        Assert.assertTrue(new Float(amount).compareTo(new Float(String.valueOf(chargeDetail.get("amountOrPercentage")))) == 0);
+        Assert.assertTrue(new Float(outstanding).compareTo(new Float(String.valueOf(chargeDetail.get("amountOutstanding")))) == 0);
+        Assert.assertTrue(new Float(amountPaid).compareTo(new Float(String.valueOf(chargeDetail.get("amountPaid")))) == 0);
+        Assert.assertTrue(new Float(amountWaived).compareTo(new Float(String.valueOf(chargeDetail.get("amountWaived")))) == 0);
+    }
+
+    private void validateChargeExcludePrecission(Integer amountPercentage, final List<HashMap> loanCharges, final String amount,
+            final String outstanding, String amountPaid, String amountWaived) {
+        DecimalFormat twoDForm = new DecimalFormat("#");
+        HashMap chargeDetail = getloanCharge(amountPercentage, loanCharges);
+        Assert.assertTrue(new Float(twoDForm.format(new Float(amount))).compareTo(new Float(twoDForm.format(new Float(String
+                .valueOf(chargeDetail.get("amountOrPercentage")))))) == 0);
+        Assert.assertTrue(new Float(twoDForm.format(new Float(outstanding))).compareTo(new Float(twoDForm.format(new Float(String
+                .valueOf(chargeDetail.get("amountOutstanding")))))) == 0);
+        Assert.assertTrue(new Float(twoDForm.format(new Float(amountPaid))).compareTo(new Float(twoDForm.format(new Float(String
+                .valueOf(chargeDetail.get("amountPaid")))))) == 0);
+        Assert.assertTrue(new Float(twoDForm.format(new Float(amountWaived))).compareTo(new Float(twoDForm.format(new Float(String
+                .valueOf(chargeDetail.get("amountWaived")))))) == 0);
+    }
+
+    public void validateNumberForEqual(String val, String val2) {
+        Assert.assertTrue(new Float(val).compareTo(new Float(val2)) == 0);
+    }
+
+    public void validateNumberForEqualWithMsg(String msg, String val, String val2) {
+        Assert.assertTrue(msg + "expected " + val + " but was " + val2, new Float(val).compareTo(new Float(val2)) == 0);
+    }
+
+    public void validateNumberForEqualExcludePrecission(String val, String val2) {
+        DecimalFormat twoDForm = new DecimalFormat("#");
+        Assert.assertTrue(new Float(twoDForm.format(new Float(val))).compareTo(new Float(twoDForm.format(new Float(val2)))) == 0);
+    }
+
+    private Integer createLoanProduct(final boolean multiDisburseLoan, final String accountingRule, final Account... accounts) {
+        System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
+        LoanProductTestBuilder builder = new LoanProductTestBuilder() //
+                .withPrincipal("12,000.00") //
+                .withNumberOfRepayments("4") //
+                .withRepaymentAfterEvery("1") //
+                .withRepaymentTypeAsMonth() //
+                .withinterestRatePerPeriod("1") //
+                .withInterestRateFrequencyTypeAsMonths() //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withInterestTypeAsDecliningBalance() //
+                .withTranches(multiDisburseLoan) //
+                .withAccounting(accountingRule, accounts);
+        if (multiDisburseLoan) {
+            builder = builder.withInterestCalculationPeriodTypeAsRepaymentPeriod(true);
+        }
+        final String loanProductJSON = builder.build(null);
+        return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+    }
+
+    private Integer createLoanProduct(final String inMultiplesOf, final String digitsAfterDecimal, final String repaymentStrategy) {
+        System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
+        final String loanProductJSON = new LoanProductTestBuilder() //
+                .withPrincipal("10000000.00") //
+                .withNumberOfRepayments("24") //
+                .withRepaymentAfterEvery("1") //
+                .withRepaymentTypeAsMonth() //
+                .withinterestRatePerPeriod("2") //
+                .withInterestRateFrequencyTypeAsMonths() //
+                .withRepaymentStrategy(repaymentStrategy) //
+                .withAmortizationTypeAsEqualPrincipalPayment() //
+                .withInterestTypeAsDecliningBalance() //
+                .currencyDetails(digitsAfterDecimal, inMultiplesOf).build(null);
+        return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+    }
+
+    private Integer createLoanProduct(final String inMultiplesOf, final String digitsAfterDecimal, final String repaymentStrategy,
+            final String accountingRule, final Account... accounts) {
+        System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
+        final String loanProductJSON = new LoanProductTestBuilder() //
+                .withPrincipal("10000000.00") //
+                .withNumberOfRepayments("24") //
+                .withRepaymentAfterEvery("1") //
+                .withRepaymentTypeAsMonth() //
+                .withinterestRatePerPeriod("2") //
+                .withInterestRateFrequencyTypeAsMonths() //
+                .withRepaymentStrategy(repaymentStrategy) //
+                .withAmortizationTypeAsEqualPrincipalPayment() //
+                .withInterestTypeAsDecliningBalance() //
+                .currencyDetails(digitsAfterDecimal, inMultiplesOf).withAccounting(accountingRule, accounts).build(null);
+        return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+    }
+
+    private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal("10000000.00") //
+                .withLoanTermFrequency("24") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("24") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualPrincipalPayments() //
+                .withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
+                .withPrincipalGrace(graceOnPrincipalPayment).withExpectedDisbursementDate("2 June 2014") //
+                .withSubmittedOnDate("2 June 2014") //
+                .build(clientID.toString(), loanProductID.toString(), null);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+    private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
+            final String savingsId, String principal) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal(principal) //
+                .withLoanTermFrequency("4") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("4") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
+                .withExpectedDisbursementDate("20 September 2011") //
+                .withSubmittedOnDate("20 September 2011") //
+                .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+    private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
+            final String savingsId, String principal, List<HashMap> tranches) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal(principal) //
+                .withLoanTermFrequency("4") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("4") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
+                .withExpectedDisbursementDate("1 March 2014") //
+                .withTranches(tranches) //
+                .withSubmittedOnDate("1 March 2014") //
+
+                .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+    private String updateLoanJson(final Integer clientID, final Integer loanProductID, List<HashMap> charges, String savingsId) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal("10,000.00") //
+                .withLoanTermFrequency("4") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("4") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
+                .withExpectedDisbursementDate("20 September 2011") //
+                .withSubmittedOnDate("20 September 2011") //
+                .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
+        return loanApplicationJSON;
+    }
+
+    private Integer applyForLoanApplicationWithPaymentStrategy(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
+            final String savingsId, String principal, final String repaymentStrategy) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal(principal) //
+                .withLoanTermFrequency("4") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("4") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
+                .withExpectedDisbursementDate("20 September 2011") //
+                .withSubmittedOnDate("20 September 2011") //
+                .withwithRepaymentStrategy(repaymentStrategy) //
+                .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+    private Integer applyForLoanApplicationWithPaymentStrategyAndPastMonth(final Integer clientID, final Integer loanProductID,
+            List<HashMap> charges, final String savingsId, String principal, final String repaymentStrategy, final int month) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+
+        Calendar fourMonthsfromNowCalendar = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        fourMonthsfromNowCalendar.add(Calendar.MONTH, month);
+        DateFormat dateFormat = new SimpleDateFormat("dd MMMMMM yyyy");
+        dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
+        String fourMonthsfromNow = dateFormat.format(fourMonthsfromNowCalendar.getTime());
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal(principal) //
+                .withLoanTermFrequency("6") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("6") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withInterestTypeAsFlatBalance() //
+                .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
+                .withExpectedDisbursementDate(fourMonthsfromNow) //
+                .withSubmittedOnDate(fourMonthsfromNow) //
+                .withwithRepaymentStrategy(repaymentStrategy) //
+                .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+    private void verifyLoanRepaymentSchedule(final ArrayList<HashMap> loanSchedule) {
+        System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
+
+        assertEquals("Checking for Due Date for 1st Month", new ArrayList<>(Arrays.asList(2011, 10, 20)), loanSchedule.get(1)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 1st Month", new Float("2911.49"), loanSchedule.get(1).get("principalOriginalDue"));
+        assertEquals("Checking for Interest Due for 1st Month", new Float("240.00"), loanSchedule.get(1).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 2nd Month", new ArrayList<>(Arrays.asList(2011, 11, 20)), loanSchedule.get(2)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 2nd Month", new Float("2969.72"), loanSchedule.get(2).get("principalDue"));
+        assertEquals("Checking for Interest Due for 2nd Month", new Float("181.77"), loanSchedule.get(2).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 3rd Month", new ArrayList<>(Arrays.asList(2011, 12, 20)), loanSchedule.get(3)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 3rd Month", new Float("3029.11"), loanSchedule.get(3).get("principalDue"));
+        assertEquals("Checking for Interest Due for 3rd Month", new Float("122.38"), loanSchedule.get(3).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 4th Month", new ArrayList<>(Arrays.asList(2012, 1, 20)), loanSchedule.get(4).get("dueDate"));
+        assertEquals("Checking for Principal Due for 4th Month", new Float("3089.68"), loanSchedule.get(4).get("principalDue"));
+        assertEquals("Checking for Interest Due for 4th Month", new Float("61.79"), loanSchedule.get(4).get("interestOriginalDue"));
+    }
+
+    private void verifyLoanRepaymentScheduleForEqualPrincipal(final ArrayList<HashMap> loanSchedule) {
+        System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
+
+        assertEquals("Checking for Due Date for 1st Month", new ArrayList<>(Arrays.asList(2014, 7, 2)), loanSchedule.get(1).get("dueDate"));
+        assertEquals("Checking for Principal Due for 1st Month", new Float("416700"), loanSchedule.get(1).get("principalOriginalDue"));
+        assertEquals("Checking for Interest Due for 1st Month", new Float("200000"), loanSchedule.get(1).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 2nd Month", new ArrayList<>(Arrays.asList(2014, 8, 2)), loanSchedule.get(2).get("dueDate"));
+        assertEquals("Checking for Principal Due for 2nd Month", new Float("416700"), loanSchedule.get(2).get("principalDue"));
+        assertEquals("Checking for Interest Due for 2nd Month", new Float("191700"), loanSchedule.get(2).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 3rd Month", new ArrayList<>(Arrays.asList(2014, 9, 2)), loanSchedule.get(3).get("dueDate"));
+        assertEquals("Checking for Principal Due for 3rd Month", new Float("416700"), loanSchedule.get(3).get("principalDue"));
+        assertEquals("Checking for Interest Due for 3rd Month", new Float("183300"), loanSchedule.get(3).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 4th Month", new ArrayList<>(Arrays.asList(2014, 10, 2)), loanSchedule.get(4).get("dueDate"));
+        assertEquals("Checking for Principal Due for 4th Month", new Float("416700"), loanSchedule.get(4).get("principalDue"));
+        assertEquals("Checking for Interest Due for 4th Month", new Float("175000"), loanSchedule.get(4).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 5th Month", new ArrayList<>(Arrays.asList(2014, 11, 2)), loanSchedule.get(5).get("dueDate"));
+        assertEquals("Checking for Principal Due for 5th Month", new Float("416700"), loanSchedule.get(5).get("principalDue"));
+        assertEquals("Checking for Interest Due for 5th Month", new Float("166700"), loanSchedule.get(5).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 6th Month", new ArrayList<>(Arrays.asList(2014, 12, 2)), loanSchedule.get(6).get("dueDate"));
+        assertEquals("Checking for Principal Due for 6th Month", new Float("416700"), loanSchedule.get(6).get("principalDue"));
+        assertEquals("Checking for Interest Due for 6th Month", new Float("158300"), loanSchedule.get(6).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 10th Month", new ArrayList<>(Arrays.asList(2015, 4, 2)), loanSchedule.get(10)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 10th Month", new Float("416700"), loanSchedule.get(10).get("principalDue"));
+        assertEquals("Checking for Interest Due for 10th Month", new Float("125000"), loanSchedule.get(10).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 20th Month", new ArrayList<>(Arrays.asList(2016, 2, 2)), loanSchedule.get(20)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 20th Month", new Float("416700"), loanSchedule.get(20).get("principalDue"));
+        assertEquals("Checking for Interest Due for 20th Month", new Float("41700"), loanSchedule.get(20).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 24th Month", new ArrayList<>(Arrays.asList(2016, 6, 2)), loanSchedule.get(24)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 24th Month", new Float("415900"), loanSchedule.get(24).get("principalDue"));
+        assertEquals("Checking for Interest Due for 24th Month", new Float("8300"), loanSchedule.get(24).get("interestOriginalDue"));
+
+    }
+
+    private void verifyLoanRepaymentScheduleForEqualPrincipalWithGrace(final ArrayList<HashMap> loanSchedule) {
+        System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
+
+        assertEquals("Checking for Due Date for 1st Month", new ArrayList<>(Arrays.asList(2014, 7, 2)), loanSchedule.get(1).get("dueDate"));
+        validateNumberForEqualWithMsg("Checking for Principal Due for 1st Month", "0.0",
+                String.valueOf(loanSchedule.get(1).get("principalOriginalDue")));
+        assertEquals("Checking for Interest Due for 1st Month", new Float("200000"), loanSchedule.get(1).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 2nd Month", new ArrayList<>(Arrays.asList(2014, 8, 2)), loanSchedule.get(2).get("dueDate"));
+        validateNumberForEqualWithMsg("Checking for Principal Due for 2nd Month", "0.0",
+                String.valueOf(loanSchedule.get(2).get("principalOriginalDue")));
+        assertEquals("Checking for Interest Due for 2nd Month", new Float("200000"), loanSchedule.get(2).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 3rd Month", new ArrayList<>(Arrays.asList(2014, 9, 2)), loanSchedule.get(3).get("dueDate"));
+        validateNumberForEqualWithMsg("Checking for Principal Due for 3rd Month", "0.0",
+                String.valueOf(loanSchedule.get(3).get("principalDue")));
+        assertEquals("Checking for Interest Due for 3rd Month", new Float("200000"), loanSchedule.get(3).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 4th Month", new ArrayList<>(Arrays.asList(2014, 10, 2)), loanSchedule.get(4).get("dueDate"));
+        validateNumberForEqualWithMsg("Checking for Principal Due for 4th Month", "0",
+                String.valueOf(loanSchedule.get(4).get("principalDue")));
+        assertEquals("Checking for Interest Due for 4th Month", new Float("200000"), loanSchedule.get(4).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 5th Month", new ArrayList<>(Arrays.asList(2014, 11, 2)), loanSchedule.get(5).get("dueDate"));
+        validateNumberForEqualWithMsg("Checking for Principal Due for 5th Month", "0",
+                String.valueOf(loanSchedule.get(5).get("principalDue")));
+        assertEquals("Checking for Interest Due for 5th Month", new Float("200000"), loanSchedule.get(5).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 6th Month", new ArrayList<>(Arrays.asList(2014, 12, 2)), loanSchedule.get(6).get("dueDate"));
+        assertEquals("Checking for Principal Due for 6th Month", new Float("526300"), loanSchedule.get(6).get("principalDue"));
+        assertEquals("Checking for Interest Due for 6th Month", new Float("200000"), loanSchedule.get(6).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 7th Month", new ArrayList<>(Arrays.asList(2015, 1, 2)), loanSchedule.get(7).get("dueDate"));
+        assertEquals("Checking for Principal Due for 7th Month", new Float("526300"), loanSchedule.get(7).get("principalDue"));
+        assertEquals("Checking for Interest Due for 7th Month", new Float("189500"), loanSchedule.get(7).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 10th Month", new ArrayList<>(Arrays.asList(2015, 4, 2)), loanSchedule.get(10)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 10th Month", new Float("526300"), loanSchedule.get(10).get("principalDue"));
+        assertEquals("Checking for Interest Due for 10th Month", new Float("157900"), loanSchedule.get(10).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 20th Month", new ArrayList<>(Arrays.asList(2016, 2, 2)), loanSchedule.get(20)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 20th Month", new Float("526300"), loanSchedule.get(20).get("principalDue"));
+        assertEquals("Checking for Interest Due for 20th Month", new Float("52600"), loanSchedule.get(20).get("interestOriginalDue"));
+
+        assertEquals("Checking for Due Date for 24th Month", new ArrayList<>(Arrays.asList(2016, 6, 2)), loanSchedule.get(24)
+                .get("dueDate"));
+        assertEquals("Checking for Principal Due for 24th Month", new Float("526600"), loanSchedule.get(24).get("principalDue"));
+        assertEquals("Checking for Interest Due for 24th Month", new Float("10500"), loanSchedule.get(24).get("interestOriginalDue"));
+
+    }
+
+    private void addCharges(List<HashMap> charges, Integer chargeId, String amount, String duedate) {
+        charges.add(charges(chargeId, amount, duedate));
+    }
+
+    private HashMap charges(Integer chargeId, String amount, String duedate) {
+        HashMap charge = new HashMap(2);
+        charge.put("chargeId", chargeId.toString());
+        charge.put("amount", amount);
+        if (duedate != null) {
+            charge.put("dueDate", duedate);
+        }
+        return charge;
+    }
+
+    private HashMap getloanCharge(Integer chargeId, List<HashMap> charges) {
+        HashMap charge = null;
+        for (HashMap loancharge : charges) {
+            if (loancharge.get("chargeId").equals(chargeId)) {
+                charge = loancharge;
+            }
+        }
+        return charge;
+    }
+
+    private List<HashMap> copyChargesForUpdate(List<HashMap> charges, Integer deleteWithChargeId, String amount) {
+        List<HashMap> loanCharges = new ArrayList<>();
+        for (HashMap charge : charges) {
+            if (!charge.get("chargeId").equals(deleteWithChargeId)) {
+                loanCharges.add(copyForUpdate(charge, amount));
+            }
+        }
+        return loanCharges;
+    }
+
+    private HashMap copyForUpdate(HashMap charge, String amount) {
+        HashMap map = new HashMap();
+        map.put("id", charge.get("id"));
+        if (amount == null) {
+            map.put("amount", charge.get("amountOrPercentage"));
+        } else {
+            map.put("amount", amount);
+        }
+        if (charge.get("dueDate") != null) {
+            map.put("dueDate", charge.get("dueDate"));
+        }
+        map.put("chargeId", charge.get("chargeId"));
+        return map;
+    }
+
+    private HashMap createTrancheDetail(final String date, final String amount) {
+        HashMap detail = new HashMap();
+        detail.put("expectedDisbursementDate", date);
+        detail.put("principal", amount);
+
+        return detail;
+    }
+
+    /***
+     * Test case for checking CashBasedAccounting functionality adding charges
+     * with calculation type flat
+     */
+    @Test
+    public void loanWithFlatCahargesAndCashBasedAccountingEnabled() {
+        this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec);
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+
+        // Add charges with payment mode regular
+        List<HashMap> charges = new ArrayList<>();
+        Integer flatDisbursement = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper.getLoanDisbursementJSON());
+        addCharges(charges, flatDisbursement, "100", null);
+        Integer flatSpecifiedDueDate = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", false));
+        addCharges(charges, flatSpecifiedDueDate, "100", "29 September 2011");
+        Integer flatInstallmentFee = ChargesHelper.createCharges(requestSpec, responseSpec,
+                ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
+        addCharges(charges, flatInstallmentFee, "50", null);
+
+        final Account assetAccount = this.accountHelper.createAssetAccount();
+        final Account incomeAccount = this.accountHelper.createIncomeAccount();
+        final Account expenseAccount = this.accountHelper.createExpenseAccount();
+        final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
+
+        final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00");
+        Assert.assertNotNull(loanID);
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+        verifyLoanRepaymentSchedule(loanSchedule);
+
+        List<HashMap> loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        validateCharge(flatDisbursement, loanCharges, "100", "100.00", "0.0", "0.0");
+        validateCharge(flatSpecifiedDueDate, loanCharges, "100", "100.00", "0.0", "0.0");
+        validateCharge(flatInstallmentFee, loanCharges, "50", "200.00", "0.0", "0.0");
+
+        // check for disbursement fee
+        HashMap disbursementDetail = loanSchedule.get(0);
+        validateNumberForEqual("100.00", String.valueOf(disbursementDetail.get("feeChargesDue")));
+
+        // check for charge at specified date and installment fee
+        HashMap firstInstallment = loanSchedule.get(1);
+        validateNumberForEqual("150.00", String.valueOf(firstInstallment.get("feeChargesDue")));
+
+        // check for installment fee
+        HashMap secondInstallment = loanSchedule.get(2);
+        validateNumberForEqual("50.00", String.valueOf(secondInstallment.get("feeChargesDue")));
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        System.out.println("-------------------------------DISBURSE LOAN-------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(Float.valueOf("100.00"), JournalEntry.TransactionType.DEBIT),
+                new JournalEntry(Float.valueOf("12000.00"), JournalEntry.TransactionType.CREDIT),
+                new JournalEntry(Float.valueOf("12000.00"), JournalEntry.TransactionType.DEBIT) };
+        this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 September 2011", assetAccountInitialEntry);
+        this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 September 2011",
+                new JournalEntry(Float.valueOf("100.00"), JournalEntry.TransactionType.CREDIT));
+        loanCharges.clear();
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        validateCharge(flatDisbursement, loanCharges, "100", "0.00", "100.0", "0.0");
+
+        System.out.println("-------------Make repayment 1-----------");
+        this.loanTransactionHelper.makeRepayment("20 October 2011", Float.valueOf("3301.49"), loanID);
+        loanCharges.clear();
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        validateCharge(flatDisbursement, loanCharges, "100", "0.00", "100.0", "0.0");
+        validateCharge(flatSpecifiedDueDate, loanCharges, "100", "0.00", "100.0", "0.0");
+        validateCharge(flatInstallmentFee, loanCharges, "50", "150.00", "50.0", "0.0");
+
+        this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 October 2011", new JournalEntry(
+                Float.valueOf("3301.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2911.49"),
+                JournalEntry.TransactionType.CREDIT));
+        this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 October 2011",
+                new JournalEntry(Float.valueOf("150.00"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("240.00"),
+                        JournalEntry.TransactionType.CREDIT));
+        this.loanTransactionHelper.addChargesForLoan(loanID, LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(
+                String.valueOf(flatSpecifiedDueDate), "29 October 2011", "100"));
+        loanSchedule.clear();
+        loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+
+        secondInstallment = loanSchedule.get(2);
+        validateNumberForEqual("150.00", String.valueOf(secondInstallment.get("feeChargesDue")));
+        this.loanTransactionHelper.waiveChargesForLoan(loanID, (Integer) getloanCharge(flatInstallmentFee, loanCharges).get("id"),
+                LoanTransactionHelper.getWaiveChargeJSON(String.valueOf(2)));
+        loanCharges.clear();
+        loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+        validateCharge(flatInstallmentFee, loanCharges, "50", "100.00", "50.0", "50.0");
+
+        System.out.println("----------Make repayment 2------------");
+        this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.49"), loanID);
+        this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
+                new JournalEntry(Float.valueOf("3251.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.72"),
+                        JournalEntry.TransactionType.CREDIT));
+        this.journalEntryHelper.checkJourna

<TRUNCATED>


Mime
View raw message