You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ma...@apache.org on 2016/01/28 06:46:54 UTC

[09/51] [partial] incubator-fineract git commit: initial code push

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/HookIntegrationTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/HookIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/HookIntegrationTest.java
new file mode 100644
index 0000000..5013a40
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/HookIntegrationTest.java
@@ -0,0 +1,115 @@
+/**
+ * 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 org.junit.Assert;
+
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.fineract.integrationtests.common.HookHelper;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.http.conn.HttpHostConnectException;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.jayway.restassured.RestAssured;
+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;
+
+public class HookIntegrationTest {
+
+    private RequestSpecification requestSpec;
+    private ResponseSpecification responseSpec;
+
+    private HookHelper hookHelper;
+    private OfficeHelper officeHelper;
+
+    @Before
+    public void setUp() throws Exception {
+        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.hookHelper = new HookHelper(this.requestSpec, this.responseSpec);
+        this.officeHelper = new OfficeHelper(this.requestSpec, this.responseSpec);
+    }
+
+    @Test
+    public void shouldSendOfficeCreationNotification() {
+        // Subject to https://echo-webhook.herokuapp.com being up
+        // See
+        // http://www.jamesward.com/2014/06/11/testing-webhooks-was-a-pain-so-i-fixed-the-glitch
+        final String payloadURL = "http://echo-webhook.herokuapp.com:80/Z7RXoCBdLSFMDrpn?";
+        this.hookHelper.createHook(payloadURL);
+        final Integer createdOfficeID = this.officeHelper.createOffice("01 January 2012");
+        try {
+
+            /**
+             * sleep for a three seconds after each failure to increase the
+             * likelihood of the previous request for creating office completing
+             **/
+
+            for (int i = 0; i < 6; i++) {
+                try {
+                    final String json = RestAssured.get(payloadURL.replace("?", "")).asString();
+                    final Integer notificationOfficeId = JsonPath.with(json).get("officeId");
+                    Assert.assertEquals("Equality check for created officeId and hook received payload officeId", createdOfficeID,
+                            notificationOfficeId);
+                    System.out.println("Notification Office Id - " + notificationOfficeId);
+                    i = 6;
+                } catch (Exception e) {
+                    TimeUnit.SECONDS.sleep(3);
+                    i++;
+                }
+            }
+
+        } catch (final Exception e) {
+            if (e instanceof HttpHostConnectException) {
+                fail("Failed to connect to https://echo-webhook.herokuapp.com platform");
+            }
+            throw new RuntimeException(e);
+        }
+
+    }
+    
+    @Test
+    public void createUpdateAndDeleteHook(){
+    	final String payloadURL = "http://echo-webhook.herokuapp.com:80/Z7RXoCBdLSFMDrpn?";
+    	final String updateURL = "http://localhost";
+
+        Long hookId = this.hookHelper.createHook(payloadURL).longValue();
+        Assert.assertNotNull(hookId);
+        this.hookHelper.verifyHookCreatedOnServer(hookId);
+    	System.out.println("---------------------SUCCESSFULLY CREATED AND VERIFIED HOOK-------------------------"+hookId);
+    	this.hookHelper.updateHook(updateURL, hookId);
+    	this.hookHelper.verifyUpdateHook(updateURL, hookId);
+    	System.out.println("---------------------SUCCESSFULLY UPDATED AND VERIFIED HOOK-------------------------"+hookId);
+    	this.hookHelper.deleteHook(hookId);
+    	this.hookHelper.verifyDeleteHook(hookId);
+    	System.out.println("---------------------SUCCESSFULLY DELETED AND VERIFIED HOOK-------------------------"+hookId);
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java
new file mode 100644
index 0000000..1ef1a20
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java
@@ -0,0 +1,281 @@
+/**
+ * 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.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.CommonConstants;
+import org.apache.fineract.integrationtests.common.Utils;
+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.junit.Before;
+import org.junit.Test;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+@SuppressWarnings("rawtypes")
+public class LoanApplicationApprovalTest {
+
+    private ResponseSpecification responseSpec;
+    private ResponseSpecification responseSpecForStatusCode403;
+    private ResponseSpecification responseSpecForStatusCode400;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+
+    @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.responseSpecForStatusCode403 = new ResponseSpecBuilder().expectStatusCode(403).build();
+        this.responseSpecForStatusCode400 = new ResponseSpecBuilder().expectStatusCode(400).build();
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+    }
+
+    /*
+     * Positive test case: Approved amount non zero is less than proposed amount
+     */
+    @Test
+    public void loanApplicationApprovedAmountLessThanProposedAmount() {
+
+        final String proposedAmount = "8000";
+        final String approvalAmount = "5000";
+        final String approveDate = "20 September 2012";
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder().build(null));
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        final String expectedDisbursementDate = null;
+        List<HashMap> approveTranches = null;
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
+                loanID, approveTranches);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+    }
+
+    /*
+     * Negative test case: Approved amount non zero is greater than proposed
+     * amount
+     */
+    @Test
+    public void loanApplicationApprovedAmountGreaterThanProposedAmount() {
+
+        final String proposedAmount = "5000";
+        final String approvalAmount = "9000";
+        final String approveDate = "20 September 2011";
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder().build(null));
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode403);
+
+        @SuppressWarnings("unchecked")
+        List<HashMap> error = (List<HashMap>) this.loanTransactionHelper.approveLoan(approveDate, approvalAmount, loanID,
+                CommonConstants.RESPONSE_ERROR);
+
+        assertEquals("error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded",
+                error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+    }
+
+    public HashMap createTrancheDetail(final String date, final String amount) {
+        HashMap<String, Object> detail = new HashMap<>();
+        detail.put("expectedDisbursementDate", date);
+        detail.put("principal", amount);
+
+        return detail;
+    }
+
+    @Test
+    public void loanApplicationApprovalAndValidationForMultiDisburseLoans() {
+
+        List<HashMap> createTranches = new ArrayList<>();
+        createTranches.add(createTrancheDetail("1 March 2014", "1000"));
+        createTranches.add(createTrancheDetail("23 March 2014", "4000"));
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
+        System.out.println("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------"
+                + clientID);
+
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
+                .withInterestTypeAsDecliningBalance().withTranches(true).withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+                .build(null));
+        System.out.println("----------------------------------LOAN PRODUCT CREATED WITH ID-------------------------------------------"
+                + loanProductID);
+
+        this.trancheLoansApprovedAmountLesserThanProposedAmount(clientID, loanProductID, createTranches);
+        this.trancheLoansApprovalValidation(clientID, loanProductID, createTranches);
+
+    }
+
+    private void trancheLoansApprovedAmountLesserThanProposedAmount(Integer clientID, Integer loanProductID, List<HashMap> createTranches) {
+        final String proposedAmount = "5000";
+        final String approvalAmount = "2000";
+        final String approveDate = "1 March 2014";
+        final String expectedDisbursementDate = "1 March 2014";
+
+        List<HashMap> approveTranches = new ArrayList<>();
+        approveTranches.add(createTrancheDetail("1 March 2014", "1000"));
+        approveTranches.add(createTrancheDetail("23 March 2014", "1000"));
+
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
+        System.out.println("-----------------------------------LOAN CREATED WITH LOANID-------------------------------------------------"
+                + loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
+                loanID, approveTranches);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+        System.out
+                .println("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------");
+
+    }
+
+    private void trancheLoansApprovalValidation(Integer clientID, Integer loanProductID, List<HashMap> createTranches) {
+        final String proposedAmount = "5000";
+        final String approvalAmount1 = "10000";
+        final String approvalAmount2 = "3000";
+        final String approvalAmount3 = "400";
+        final String approvalAmount4 = "200";
+
+        final String approveDate = "1 March 2014";
+        final String expectedDisbursementDate = "1 March 2014";
+
+        List<HashMap> approveTranche1 = new ArrayList<>();
+        approveTranche1.add(createTrancheDetail("1 March 2014", "5000"));
+        approveTranche1.add(createTrancheDetail("23 March 2014", "5000"));
+
+        List<HashMap> approveTranche2 = new ArrayList<>();
+        approveTranche2.add(createTrancheDetail("1 March 2014", "1000"));
+        approveTranche2.add(createTrancheDetail("23 March 2014", "1000"));
+        approveTranche2.add(createTrancheDetail("23 March 2014", "1000"));
+
+        List<HashMap> approveTranche3 = new ArrayList<>();
+        approveTranche3.add(createTrancheDetail("1 March 2014", "100"));
+        approveTranche3.add(createTrancheDetail("23 March 2014", "100"));
+        approveTranche3.add(createTrancheDetail("24 March 2014", "100"));
+        approveTranche3.add(createTrancheDetail("25 March 2014", "100"));
+
+        List<HashMap> approveTranche4 = new ArrayList<>();
+        approveTranche4.add(createTrancheDetail("1 March 2014", "100"));
+        approveTranche4.add(createTrancheDetail("23 March 2014", "100"));
+        approveTranche4.add(createTrancheDetail("24 March 2014", "100"));
+
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
+        System.out.println("-----------------------------------LOAN CREATED WITH LOANID-------------------------------------------------"
+                + loanID);
+
+        HashMap<String, Object> loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode400);
+
+        /* Tranches with same expected disbursement date */
+        List<HashMap<String, Object>> error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate,
+                approvalAmount2, loanID, approveTranche2, CommonConstants.RESPONSE_ERROR);
+        assertEquals("validation.msg.loan.expectedDisbursementDate.disbursement.date.must.be.unique.for.tranches",
+                error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+        /* Sum of tranches is greater than approved amount */
+        error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, approvalAmount4, loanID,
+                approveTranche4, CommonConstants.RESPONSE_ERROR);
+        assertEquals("validation.msg.loan.principal.sum.of.multi.disburse.amounts.must.be.equal.to.or.lesser.than.approved.principal",
+                error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode403);
+
+        /* Sum of tranches exceeds the proposed amount */
+        error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, approvalAmount1, loanID,
+                approveTranche1, CommonConstants.RESPONSE_ERROR);
+        assertEquals("error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded",
+                error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+        /* No. of tranches exceeds the max tranche count at product level */
+        error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, approvalAmount3, loanID,
+                approveTranche3, CommonConstants.RESPONSE_ERROR);
+        assertEquals("error.msg.disbursementData.exceeding.max.tranche.count", error.get(0)
+                .get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+        /* If tranches are not specified for a multi-disburse loan */
+        /**
+         * error =
+         * this.loanTransactionHelper.approveLoanForTranches(approveDate,
+         * expectedDisbursementDate, approvalAmount5, loanID, approveTranche5,
+         * CommonConstants.RESPONSE_ERROR);
+         * assertEquals("error.msg.disbursementData.required",
+         * error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+         **/
+    }
+
+    private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) {
+        final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5")
+                .withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012")
+                .withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null);
+        return this.loanTransactionHelper.getLoanId(loanApplication);
+    }
+
+    public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
+            List<HashMap> tranches) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder()
+        //
+                .withPrincipal(principal)
+                //
+                .withLoanTermFrequency("5")
+                //
+                .withLoanTermFrequencyAsMonths()
+                //
+                .withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate("1 March 2014") //
+                .withTranches(tranches) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate("1 March 2014") //
+                .build(clientID.toString(), loanProductID.toString(), null);
+
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
new file mode 100644
index 0000000..672972e
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
@@ -0,0 +1,157 @@
+/**
+ * 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 java.math.BigDecimal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.fineract.integrationtests.LoanApplicationApprovalTest;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+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.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+@SuppressWarnings("rawtypes")
+public class LoanApplicationUndoLastTrancheTest {
+
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private LoanApplicationApprovalTest loanApplicationApprovalTest;
+
+    @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.loanApplicationApprovalTest = new LoanApplicationApprovalTest();
+    }
+
+    @Test
+    public void LoanApplicationUndoLastTranche() {
+
+        final String proposedAmount = "5000";
+        final String approvalAmount = "2000";
+        final String approveDate = "1 March 2014";
+        final String expectedDisbursementDate = "1 March 2014";
+        final String disbursalDate = "1 March 2014";
+
+        // CREATE CLIENT
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
+        System.out.println("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------"
+                + clientID);
+
+        // CREATE LOAN MULTIDISBURSAL PRODUCT
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
+                .withInterestTypeAsDecliningBalance().withTranches(true).withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+                .build(null));
+        System.out.println("----------------------------------LOAN PRODUCT CREATED WITH ID-------------------------------------------"
+                + loanProductID);
+
+        // CREATE TRANCHES
+        List<HashMap> createTranches = new ArrayList<>();
+        createTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("1 March 2014", "1000"));
+        createTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("23 June 2014", "4000"));
+
+        // APPROVE TRANCHES
+        List<HashMap> approveTranches = new ArrayList<>();
+        approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("1 March 2014", "1000"));
+        approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("23 June 2014", "1000"));
+
+        // APPLY FOR LOAN WITH TRANCHES
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
+        System.out.println("-----------------------------------LOAN CREATED WITH LOANID-------------------------------------------------"
+                + loanID);
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+
+        // VALIDATE THE LOAN STATUS
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
+                loanID, approveTranches);
+
+        // VALIDATE THE LOAN IS APPROVED
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        // DISBURSE A LOAN
+        this.loanTransactionHelper.disburseLoan(disbursalDate, loanID);
+        loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        System.out.println("-------------Make repayment 1-----------");
+        this.loanTransactionHelper.makeRepayment("01 April 2014", Float.valueOf("420"), loanID);
+        System.out.println("-------------Make repayment 2-----------");
+        this.loanTransactionHelper.makeRepayment("01 May 2014", Float.valueOf("412"), loanID);
+        System.out.println("-------------Make repayment 3-----------");
+        this.loanTransactionHelper.makeRepayment("01 June 2014", Float.valueOf("204"), loanID);
+        // DISBURSE A SECOND TRANCHE
+        this.loanTransactionHelper.disburseLoan("23 June 2014", loanID);
+        // UNDO LAST TRANCHE
+        Float disbursedAmount = this.loanTransactionHelper.undoLastDisbursal(loanID);
+        validateDisbursedAmount(disbursedAmount);
+    }
+
+    private void validateDisbursedAmount(Float disbursedAmount) {
+        Assert.assertEquals(Float.valueOf("1000.0"), disbursedAmount);
+
+    }
+
+    public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
+            List<HashMap> tranches) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder()
+        //
+                .withPrincipal(principal)
+                //
+                .withLoanTermFrequency("5")
+                //
+                .withLoanTermFrequencyAsMonths()
+                //
+                .withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate("1 March 2014") //
+                .withTranches(tranches) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate("1 March 2014") //
+                .build(clientID.toString(), loanProductID.toString(), null);
+
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java
new file mode 100644
index 0000000..cecac3d
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java
@@ -0,0 +1,501 @@
+/**
+ * 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.math.MathContext;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanDisbursementTestBuilder;
+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.junit.Before;
+import org.junit.Test;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public class LoanDisbursementDetailsIntegrationTest {
+
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private Integer loanID;
+    private Integer disbursementId;
+    final String approveDate = "01 March 2014";
+    final String expectedDisbursementDate = "01 March 2014";
+    final String proposedAmount = "5000";
+    final String approvalAmount = "5000";
+
+    @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);
+    }
+
+    @Test
+    public void createAndValidateMultiDisburseLoansBasedOnEmi() {
+        List<HashMap> createTranches = new ArrayList<>();
+        String id = null;
+        String installmentAmount = "800";
+        String withoutInstallmentAmount = "";
+        String proposedAmount = "10000";
+        createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 June 2015", "5000"));
+        createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 Sep 2015", "5000"));
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
+        System.out.println("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------"
+                + clientID);
+
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
+                .withInterestTypeAsDecliningBalance().withMoratorium("", "").withAmortizationTypeAsEqualInstallments().withTranches(true)
+                .withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
+        System.out.println("----------------------------------LOAN PRODUCT CREATED WITH ID-------------------------------------------"
+                + loanProductID);
+
+        final Integer loanIDWithEmi = applyForLoanApplicationWithEmiAmount(clientID, loanProductID, proposedAmount, createTranches,
+                installmentAmount);
+
+        System.out
+                .println("-----------------------------------LOAN CREATED WITH EMI LOANID-------------------------------------------------"
+                        + loanIDWithEmi);
+
+        HashMap repaymentScheduleWithEmi = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec,
+                loanIDWithEmi, "repaymentSchedule");
+
+        ArrayList<HashMap> periods = (ArrayList<HashMap>) repaymentScheduleWithEmi.get("periods");
+        assertEquals(periods.size(), 15);
+
+        this.validateRepaymentScheduleWithEMI(periods);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanIDWithEmi);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount("01 June 2015", "01 June 2015", "10000", loanIDWithEmi,
+                createTranches);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+        System.out
+                .println("-----------------------------------MULTI DISBURSAL LOAN WITH EMI APPROVED SUCCESSFULLY---------------------------------------");
+
+        final Integer loanIDWithoutEmi = applyForLoanApplicationWithEmiAmount(clientID, loanProductID, proposedAmount, createTranches,
+                withoutInstallmentAmount);
+
+        HashMap repaymentScheduleWithoutEmi = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec,
+                loanIDWithoutEmi, "repaymentSchedule");
+
+        ArrayList<HashMap> periods1 = (ArrayList<HashMap>) repaymentScheduleWithEmi.get("periods");
+        assertEquals(periods1.size(), 15);
+
+        System.out
+                .println("-----------------------------------LOAN CREATED WITHOUT EMI LOANID-------------------------------------------------"
+                        + loanIDWithoutEmi);
+
+        /* To be uncommented once issue MIFOSX-2006 is closed. */
+        // this.validateRepaymentScheduleWithoutEMI(periods1);
+
+        HashMap loanStatusMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanIDWithoutEmi);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount("01 June 2015", "01 June 2015", "10000",
+                loanIDWithoutEmi, createTranches);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+        System.out
+                .println("-----------------------------------MULTI DISBURSAL LOAN WITHOUT EMI APPROVED SUCCESSFULLY---------------------------------------");
+
+    }
+
+    private void validateRepaymentScheduleWithEMI(ArrayList<HashMap> periods) {
+        LoanDisbursementTestBuilder expectedRepaymentSchedule0 = new LoanDisbursementTestBuilder("[2015, 6, 1]", 0.0f, 0.0f, null, null,
+                5000.0f, null, null, null);
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule1 = new LoanDisbursementTestBuilder("[2015, 7, 1]", 800f, 800.0f, 50.0f,
+                750.0f, 4250.0f, 750.0f, 750.0f, "[2015, 6, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule2 = new LoanDisbursementTestBuilder("[2015, 8, 1]", 800.0f, 800.0f, 42.5f,
+                757.5f, 3492.5f, 757.5f, 757.5f, "[2015, 7, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule3 = new LoanDisbursementTestBuilder("[2015, 9, 1]", 0.0f, 0.0f, null, null,
+                5000.0f, null, null, null);
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule4 = new LoanDisbursementTestBuilder("[2015, 9, 1]", 800.0f, 800.0f, 34.92f,
+                765.08f, 7727.42f, 765.08f, 765.08f, "[2015, 8, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule5 = new LoanDisbursementTestBuilder("[2015, 10, 1]", 800.0f, 800.0f, 77.27f,
+                722.73f, 7004.69f, 722.73f, 722.73f, "[2015, 9, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule6 = new LoanDisbursementTestBuilder("[2015, 11, 1]", 800.0f, 800.0f, 70.05f,
+                729.95f, 6274.74f, 729.95f, 729.95f, "[2015, 10, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule7 = new LoanDisbursementTestBuilder("[2015, 12, 1]", 800.0f, 800.0f, 62.75f,
+                737.25f, 5537.49f, 737.25f, 737.25f, "[2015, 11, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule8 = new LoanDisbursementTestBuilder("[2016, 1, 1]", 800.0f, 800.0f, 55.37f,
+                744.63f, 4792.86f, 744.63f, 744.63f, "[2015, 12, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule9 = new LoanDisbursementTestBuilder("[2016, 2, 1]", 800.0f, 800.0f, 47.93f,
+                752.07f, 4040.79f, 752.07f, 752.07f, "[2016, 1, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule10 = new LoanDisbursementTestBuilder("[2016, 3, 1]", 800.0f, 800.0f, 40.41f,
+                759.59f, 3281.2f, 759.59f, 759.59f, "[2016, 2, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule11 = new LoanDisbursementTestBuilder("[2016, 4, 1]", 800.0f, 800.0f, 32.81f,
+                767.19f, 2514.01f, 767.19f, 767.19f, "[2016, 3, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule12 = new LoanDisbursementTestBuilder("[2016, 5, 1]", 800.0f, 800.0f, 25.14f,
+                774.86f, 1739.15f, 774.86f, 774.86f, "[2016, 4, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule13 = new LoanDisbursementTestBuilder("[2016, 6, 1]", 800.0f, 800.0f, 17.39f,
+                782.61f, 956.54f, 782.61f, 782.61f, "[2016, 5, 1]");
+
+        LoanDisbursementTestBuilder expectedRepaymentSchedule14 = new LoanDisbursementTestBuilder("[2016, 7, 1]", 966.11f, 966.11f, 9.57f,
+                956.54f, 0.0f, 956.54f, 956.54f, "[2016, 6, 1]");
+
+        ArrayList<LoanDisbursementTestBuilder> list = new ArrayList<LoanDisbursementTestBuilder>();
+        list.add(expectedRepaymentSchedule0);
+        list.add(expectedRepaymentSchedule1);
+        list.add(expectedRepaymentSchedule2);
+        list.add(expectedRepaymentSchedule3);
+        list.add(expectedRepaymentSchedule4);
+        list.add(expectedRepaymentSchedule5);
+        list.add(expectedRepaymentSchedule6);
+        list.add(expectedRepaymentSchedule7);
+        list.add(expectedRepaymentSchedule8);
+        list.add(expectedRepaymentSchedule9);
+        list.add(expectedRepaymentSchedule10);
+        list.add(expectedRepaymentSchedule11);
+        list.add(expectedRepaymentSchedule12);
+        list.add(expectedRepaymentSchedule13);
+        list.add(expectedRepaymentSchedule14);
+
+        for (int i = 0; i < list.size(); i++) {
+            this.assertRepaymentScheduleValuesWithEMI(periods.get(i), list.get(i), i);
+        }
+    }
+
+    private void assertRepaymentScheduleValuesWithEMI(HashMap period, LoanDisbursementTestBuilder expectedRepaymentSchedule, int position) {
+
+        assertEquals(period.get("dueDate").toString(), expectedRepaymentSchedule.getDueDate());
+        assertEquals(period.get("principalLoanBalanceOutstanding"), expectedRepaymentSchedule.getPrincipalLoanBalanceOutstanding());
+        System.out.println(period.get("totalOriginalDueForPeriod").toString());
+        assertEquals(new Float(period.get("totalOriginalDueForPeriod").toString()), expectedRepaymentSchedule
+                .getTotalOriginalDueForPeriod().floatValue(), 0.0f);
+
+        assertEquals(new Float(period.get("totalOutstandingForPeriod").toString()).floatValue(),
+                expectedRepaymentSchedule.getTotalOutstandingForPeriod(), 0.0f);
+
+        if (position != 0 && position != 3) {
+
+            assertEquals(new Float(period.get("interestOutstanding").toString()).floatValue(),
+                    expectedRepaymentSchedule.getInterestOutstanding(), 0.0f);
+            assertEquals(new Float(period.get("principalOutstanding").toString()).floatValue(),
+                    expectedRepaymentSchedule.getPrincipalOutstanding(), 0.0f);
+            assertEquals(new Float(period.get("principalDue").toString()).floatValue(), expectedRepaymentSchedule.getPrincipalDue(), 0.0f);
+            assertEquals(new Float(period.get("principalOriginalDue").toString()).floatValue(),
+                    expectedRepaymentSchedule.getPrincipalOriginalDue(), 0.0f);
+            assertEquals(period.get("fromDate").toString(), expectedRepaymentSchedule.getFromDate());
+        }
+    }
+
+    /* Uncomment and modify test builder values once MIFOSX-2006 is closed. */
+    /*
+     * private void validateRepaymentScheduleWithoutEMI(ArrayList<HashMap>
+     * periods){ LoanDisbursementTestBuilder expectedRepaymentSchedule0 = new
+     * LoanDisbursementTestBuilder( "[2015, 6, 1]", 0.0f, 0.0f, null, null,
+     * 5000.0f, null, null, null);
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule1 = new
+     * LoanDisbursementTestBuilder( "[2015, 7, 1]", 800.0f, 800.0f, 50.0f,
+     * 750.0f, 4250.0f, 750.0f, 750.0f, "[2015, 6, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule2 = new
+     * LoanDisbursementTestBuilder( "[2015, 8, 1]", 800.0f, 800.0f, 42.5f,
+     * 757.5f, 3492.5f, 757.5f, 757.5f, "[2015, 7, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule3 = new
+     * LoanDisbursementTestBuilder( "[2015, 9, 1]", 0.0f, 0.0f, null, null,
+     * 5000.0f, null, null, null);
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule4 = new
+     * LoanDisbursementTestBuilder( "[2015, 9, 1]", 800.0f, 800.0f, 34.92f,
+     * 765.08f, 7727.42f, 765.08f, 765.08f, "[2015, 8, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule5 = new
+     * LoanDisbursementTestBuilder( "[2015, 10, 1]", 800.0f, 800.0f, 77.27f,
+     * 722.73f, 7004.69f, 722.73f, 722.73f, "[2015, 9, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule6 = new
+     * LoanDisbursementTestBuilder( "[2015, 11, 1]", 800.0f, 800.0f, 70.05f,
+     * 729.95f, 6274.74f, 729.95f, 729.95f, "[2015, 10, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule7 = new
+     * LoanDisbursementTestBuilder( "[2015, 12, 1]", 800.0f, 800.0f, 62.75f,
+     * 737.25f, 5537.49f, 737.25f, 737.25f, "[2015, 11, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule8 = new
+     * LoanDisbursementTestBuilder( "[2016, 1, 1]", 800.0f, 800.0f, 55.37f,
+     * 744.63f, 4792.86f, 744.63f, 744.63f, "[2015, 12, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule9 = new
+     * LoanDisbursementTestBuilder( "[2016, 2, 1]", 800.0f, 800.0f, 47.93f,
+     * 752.07f, 4040.79f, 752.07f, 752.07f, "[2016, 1, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule10 = new
+     * LoanDisbursementTestBuilder( "[2016, 3, 1]", 800.0f, 800.0f, 40.41f,
+     * 759.59f, 3281.2f, 759.59f, 759.59f, "[2016, 2, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule11 = new
+     * LoanDisbursementTestBuilder( "[2016, 4, 1]", 800.0f, 800.0f, 32.81f,
+     * 767.19f, 2514.01f, 767.19f, 767.19f, "[2016, 3, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule12 = new
+     * LoanDisbursementTestBuilder( "[2016, 5, 1]", 800.0f, 800.0f, 25.14f,
+     * 774.86f, 1739.15f, 774.86f, 774.86f, "[2016, 4, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule13 = new
+     * LoanDisbursementTestBuilder( "[2016, 6, 1]", 800.0f, 800.0f, 17.39f,
+     * 782.61f, 956.54f, 782.61f, 782.61f, "[2016, 5, 1]");
+     * 
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule14 = new
+     * LoanDisbursementTestBuilder( "[2016, 7, 1]", 966.11f, 966.11f, 9.57f,
+     * 956.54f, 0.0f, 956.54f, 956.54f, "[2016, 6, 1]");
+     * 
+     * ArrayList<LoanDisbursementTestBuilder> list = new
+     * ArrayList<LoanDisbursementTestBuilder>();
+     * list.add(expectedRepaymentSchedule0);
+     * list.add(expectedRepaymentSchedule1);
+     * list.add(expectedRepaymentSchedule2);
+     * list.add(expectedRepaymentSchedule3);
+     * list.add(expectedRepaymentSchedule4);
+     * list.add(expectedRepaymentSchedule5);
+     * list.add(expectedRepaymentSchedule6);
+     * list.add(expectedRepaymentSchedule7);
+     * list.add(expectedRepaymentSchedule8);
+     * list.add(expectedRepaymentSchedule9);
+     * list.add(expectedRepaymentSchedule10);
+     * list.add(expectedRepaymentSchedule11);
+     * list.add(expectedRepaymentSchedule12);
+     * list.add(expectedRepaymentSchedule13);
+     * list.add(expectedRepaymentSchedule14);
+     * 
+     * for (int i = 0; i < list.size(); i++) {
+     * this.assertRepaymentScheduleValuesWithoutEMI(periods.get(i), list.get(i),
+     * i); } }
+     * 
+     * private void assertRepaymentScheduleValuesWithoutEMI(HashMap period,
+     * LoanDisbursementTestBuilder expectedRepaymentSchedule, int position) {
+     * 
+     * assertEquals(period.get("dueDate").toString(),
+     * expectedRepaymentSchedule.getDueDate());
+     * assertEquals(period.get("principalLoanBalanceOutstanding"),
+     * expectedRepaymentSchedule.getPrincipalLoanBalanceOutstanding());
+     * assertEquals(period.get("totalOriginalDueForPeriod"),
+     * expectedRepaymentSchedule.getTotalOriginalDueForPeriod());
+     * assertEquals(period.get("totalOutstandingForPeriod"),
+     * expectedRepaymentSchedule.getTotalOutstandingForPeriod());
+     * 
+     * if (position != 0 && position != 3) {
+     * 
+     * assertEquals(period.get("interestOutstanding"),
+     * expectedRepaymentSchedule.getInterestOutstanding());
+     * assertEquals(period.get("principalOutstanding"),
+     * expectedRepaymentSchedule.getPrincipalOutstanding());
+     * assertEquals(period.get("principalDue"),
+     * expectedRepaymentSchedule.getPrincipalDue());
+     * assertEquals(period.get("principalOriginalDue"),
+     * expectedRepaymentSchedule.getPrincipalOriginalDue());
+     * assertEquals(period.get("fromDate").toString(),
+     * expectedRepaymentSchedule.getFromDate()); } }
+     */
+    private Integer applyForLoanApplicationWithEmiAmount(final Integer clientID, final Integer loanProductID, final String proposedAmount,
+            List<HashMap> tranches, final String installmentAmount) {
+
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder()
+        //
+                .withPrincipal(proposedAmount)
+                //
+                .withLoanTermFrequency("12")
+                //
+                .withLoanTermFrequencyAsMonths()
+                //
+                .withNumberOfRepayments("12").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("1") //
+                .withExpectedDisbursementDate("01 June 2015") //
+                .withTranches(tranches) //
+                .withFixedEmiAmount(installmentAmount) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate("01 June 2015") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .build(clientID.toString(), loanProductID.toString(), null);
+
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+
+    }
+
+    @Test
+    public void createApproveAndValidateMultiDisburseLoan() {
+
+        List<HashMap> createTranches = new ArrayList<>();
+        String id = null;
+        createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 March 2014", "1000"));
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
+        System.out.println("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------"
+                + clientID);
+
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
+                .withInterestTypeAsDecliningBalance().withTranches(true).withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+                .build(null));
+        System.out.println("----------------------------------LOAN PRODUCT CREATED WITH ID-------------------------------------------"
+                + loanProductID);
+
+        this.loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
+        System.out.println("-----------------------------------LOAN CREATED WITH LOANID-------------------------------------------------"
+                + loanID);
+
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
+                loanID, createTranches);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+        System.out
+                .println("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------");
+        ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
+                this.responseSpec, this.loanID, "disbursementDetails");
+        this.disbursementId = (Integer) disbursementDetails.get(0).get("id");
+        this.editLoanDisbursementDetails();
+    }
+
+    private void editLoanDisbursementDetails() {
+        this.editDateAndPrincipalOfExistingTranche();
+        this.addNewDisbursementDetails();
+        this.deleteDisbursmentDetails();
+    }
+
+    private void addNewDisbursementDetails() {
+        List<HashMap> addTranches = new ArrayList<>();
+        ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
+                this.responseSpec, this.loanID, "disbursementDetails");
+        ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(0).get("expectedDisbursementDate");
+        String date = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
+
+        String id = null;
+        addTranches.add(this.loanTransactionHelper.createTrancheDetail(disbursementDetails.get(0).get("id").toString(), date,
+                disbursementDetails.get(0).get("principal").toString()));
+        addTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "3 March 2014", "2000"));
+        addTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "4 March 2014", "500"));
+
+        /* Add disbursement detail */
+        this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanID, this.approvalAmount, this.expectedDisbursementDate,
+                addTranches, "");
+    }
+
+    private void deleteDisbursmentDetails() {
+        List<HashMap> deleteTranches = new ArrayList<>();
+        ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
+                this.responseSpec, this.loanID, "disbursementDetails");
+        /* Delete the last tranche */
+        for (int i = 0; i < disbursementDetails.size() - 1; i++) {
+            ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(i).get("expectedDisbursementDate");
+            String disbursementDate = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
+            deleteTranches.add(this.loanTransactionHelper.createTrancheDetail(disbursementDetails.get(i).get("id").toString(),
+                    disbursementDate, disbursementDetails.get(i).get("principal").toString()));
+        }
+
+        /* Add disbursement detail */
+        this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanID, this.approvalAmount, this.expectedDisbursementDate,
+                deleteTranches, "");
+    }
+
+    private void editDateAndPrincipalOfExistingTranche() {
+        String updatedExpectedDisbursementDate = "01 March 2014";
+        String updatedPrincipal = "900";
+        /* Update */
+        this.loanTransactionHelper.editDisbursementDetail(this.loanID, this.disbursementId, this.approvalAmount,
+                this.expectedDisbursementDate, updatedExpectedDisbursementDate, updatedPrincipal, "");
+        /* Validate Edit */
+        ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
+                this.responseSpec, this.loanID, "disbursementDetails");
+        assertEquals(Float.valueOf(updatedPrincipal), disbursementDetails.get(0).get("principal"));
+        ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(0).get("expectedDisbursementDate");
+        String date = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
+        assertEquals(updatedExpectedDisbursementDate, date);
+
+    }
+
+    private String formatExpectedDisbursementDate(String expectedDisbursementDate) {
+
+        SimpleDateFormat source = new SimpleDateFormat("[yyyy, MM, dd]");
+        SimpleDateFormat target = new SimpleDateFormat("dd MMMM yyyy");
+        String date = null;
+        try {
+            date = target.format(source.parse(expectedDisbursementDate));
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return date;
+    }
+
+    private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
+            List<HashMap> tranches) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder()
+        //
+                .withPrincipal(principal)
+                //
+                .withLoanTermFrequency("5")
+                //
+                .withLoanTermFrequencyAsMonths()
+                //
+                .withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate("01 March 2014") //
+                .withTranches(tranches) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate("01 March 2014") //
+                .build(clientID.toString(), loanProductID.toString(), null);
+
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java
new file mode 100644
index 0000000..d0018cd
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java
@@ -0,0 +1,241 @@
+/**
+ * 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.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.Utils;
+import org.apache.fineract.integrationtests.common.accounting.Account;
+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.junit.Before;
+import org.junit.Test;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+@SuppressWarnings("rawtypes")
+public class LoanRepaymentRescheduleAtDisbursementTest {
+
+	private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private LoanApplicationApprovalTest loanApplicationApprovalTest;
+    private ResponseSpecification generalResponseSpec;
+    
+    @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.loanApplicationApprovalTest = new LoanApplicationApprovalTest();
+        this.generalResponseSpec = new ResponseSpecBuilder().build();
+    }
+    
+	@SuppressWarnings("unchecked")
+	@Test
+    public void testLoanRepaymentRescheduleAtDisbursement(){
+    	
+        final String approvalAmount = "10000";
+        final String approveDate = "01 March 2015";
+        final String expectedDisbursementDate = "01 March 2015";
+        final String disbursementDate = "01 March 2015";
+        final String adjustRepaymentDate = "16 March 2015";
+        final String recalculationRestFrequencyDate = "01 January 2012";
+         
+        // CREATE CLIENT
+    	final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
+        System.out.println("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------"
+                + clientID);
+
+        // CREATE LOAN MULTIDISBURSAL PRODUCT WITH INTEREST RECALCULATION 
+        final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY,
+                LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
+                LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
+                LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "0", recalculationRestFrequencyDate,
+                LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null);
+        
+        // CREATE TRANCHES
+        List<HashMap> createTranches = new ArrayList<>();
+        createTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 March 2015", "5000"));
+        createTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 May 2015", "5000"));
+    	
+        // APPROVE TRANCHES
+        List<HashMap> approveTranches = new ArrayList<>();
+        approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 March 2015", "5000"));
+        approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 May 2015", "5000"));
+        
+        // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION 
+        final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate,
+        		recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0), createTranches);
+        
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        
+        // VALIDATE THE LOAN STATUS
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
+                loanID, approveTranches);
+        
+        // VALIDATE THE LOAN IS APPROVED
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+        
+        // DISBURSE A FIRST TRANCHE
+        this.loanTransactionHelper.disburseLoanWithRepaymentReschedule(disbursementDate, loanID, adjustRepaymentDate);
+        loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+        
+        ArrayList<HashMap> loanRepaymnetSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, generalResponseSpec, loanID);
+        HashMap firstInstallement  = loanRepaymnetSchedule.get(1);
+        Map<String, Object> expectedvalues = new HashMap<>(3);
+        Calendar date = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        date.set(2015, Calendar.MARCH, 16);
+        expectedvalues.put("dueDate", getDateAsArray(date, 0));
+        expectedvalues.put("principalDue", "834.71");
+        expectedvalues.put("interestDue", "49.32");
+        expectedvalues.put("feeChargesDue", "0");
+        expectedvalues.put("penaltyChargesDue", "0");
+        expectedvalues.put("totalDueForPeriod", "884.03");
+        
+        // VALIDATE REPAYMENT SCHEDULE
+        verifyLoanRepaymentSchedule(firstInstallement, expectedvalues);
+        
+    }
+	
+	private void verifyLoanRepaymentSchedule(final HashMap firstInstallement, final Map<String, Object> expectedvalues) {
+       
+		assertEquals(expectedvalues.get("dueDate"), firstInstallement.get("dueDate"));
+		assertEquals(String.valueOf(expectedvalues.get("principalDue")), String.valueOf(firstInstallement.get("principalDue")));
+		assertEquals(String.valueOf(expectedvalues.get("interestDue")), String.valueOf(firstInstallement.get("interestDue")));
+		assertEquals(String.valueOf(expectedvalues.get("feeChargesDue")), String.valueOf(firstInstallement.get("feeChargesDue")));
+		assertEquals(String.valueOf(expectedvalues.get("penaltyChargesDue")), String.valueOf(firstInstallement.get("penaltyChargesDue")));
+		assertEquals(String.valueOf(expectedvalues.get("totalDueForPeriod")), String.valueOf(firstInstallement.get("totalDueForPeriod")));
+
+    }
+    
+    private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy,
+            final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod,
+            final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval,
+            final String recalculationRestFrequencyDate, final String preCloseInterestCalculationStrategy, final Account[] accounts) {
+        final String recalculationCompoundingFrequencyType = null;
+        final String recalculationCompoundingFrequencyInterval = null;
+        final String recalculationCompoundingFrequencyDate = null;
+        return createLoanProductWithInterestRecalculation(repaymentStrategy, interestRecalculationCompoundingMethod,
+                rescheduleStrategyMethod, recalculationRestFrequencyType, recalculationRestFrequencyInterval,
+                recalculationRestFrequencyDate, recalculationCompoundingFrequencyType, recalculationCompoundingFrequencyInterval,
+                recalculationCompoundingFrequencyDate, preCloseInterestCalculationStrategy, accounts, null, false);
+    }
+    
+    private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy,
+            final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod,
+            final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval,
+            final String recalculationRestFrequencyDate, final String recalculationCompoundingFrequencyType,
+            final String recalculationCompoundingFrequencyInterval, final String recalculationCompoundingFrequencyDate,
+            final String preCloseInterestCalculationStrategy, final Account[] accounts, final String chargeId,
+            boolean isArrearsBasedOnOriginalSchedule) {
+        System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
+        LoanProductTestBuilder builder = new LoanProductTestBuilder()
+                .withPrincipal("10000.00")
+                .withNumberOfRepayments("12")
+                .withRepaymentAfterEvery("2")
+                .withRepaymentTypeAsWeek()
+                .withinterestRatePerPeriod("2")
+                .withInterestRateFrequencyTypeAsMonths()
+                .withTranches(true)
+                .withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+                .withRepaymentStrategy(repaymentStrategy)
+                .withInterestTypeAsDecliningBalance()
+                .withInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod,
+                        preCloseInterestCalculationStrategy)
+                .withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, recalculationRestFrequencyInterval,
+                        recalculationRestFrequencyDate)
+                .withInterestRecalculationCompoundingFrequencyDetails(recalculationCompoundingFrequencyType,
+                        recalculationCompoundingFrequencyInterval, recalculationCompoundingFrequencyDate);
+        if (accounts != null) {
+            builder = builder.withAccountingRulePeriodicAccrual(accounts);
+        }
+
+        if (isArrearsBasedOnOriginalSchedule) builder = builder.withArrearsConfiguration();
+
+        final String loanProductJSON = builder.build(chargeId);
+        return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+    }
+    
+    private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID,
+            final String disbursementDate, final String restStartDate, final String repaymentStrategy, final List<HashMap> charges, List<HashMap> tranches) {
+        final String graceOnInterestPayment = null;
+        final String compoundingStartDate = null;
+        final String graceOnPrincipalPayment = null;
+        return applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate, restStartDate,
+                compoundingStartDate, repaymentStrategy, charges, graceOnInterestPayment, graceOnPrincipalPayment,tranches);
+    }
+    
+    private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID,
+            final String disbursementDate, final String restStartDate, final String compoundingStartDate, final String repaymentStrategy,
+            final List<HashMap> charges, final String graceOnInterestPayment, final String graceOnPrincipalPayment, List<HashMap> tranches) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal("10000.00") //
+                .withLoanTermFrequency("24") //
+                .withLoanTermFrequencyAsWeeks() //
+                .withNumberOfRepayments("12") //
+                .withRepaymentEveryAfter("2") //
+                .withRepaymentFrequencyTypeAsWeeks() //
+                .withInterestRatePerPeriod("2") //
+                .withAmortizationTypeAsEqualInstallments() //
+                .withTranches(tranches)
+                .withFixedEmiAmount("") //
+                .withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeAsDays() //
+                .withInterestCalculationPeriodTypeAsDays() //
+                .withExpectedDisbursementDate(disbursementDate) //
+                .withSubmittedOnDate(disbursementDate) //
+                .withRestFrequencyDate(restStartDate)//
+                .withwithRepaymentStrategy(repaymentStrategy) //
+                .withCharges(charges)//
+                .build(clientID.toString(), loanProductID.toString(), null);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+    
+    private List getDateAsArray(Calendar date, int addPeriod) {
+        return getDateAsArray(date, addPeriod, Calendar.DAY_OF_MONTH);
+    }
+
+    private List getDateAsArray(Calendar date, int addvalue, int type) {
+    	date.add(type, addvalue);
+        return new ArrayList<>(Arrays.asList(date.get(Calendar.YEAR), date.get(Calendar.MONTH) + 1,
+        		date.get(Calendar.DAY_OF_MONTH)));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/4b1ec9ef/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
new file mode 100644
index 0000000..2b00a98
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
@@ -0,0 +1,219 @@
+/**
+ * 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 static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanRescheduleRequestTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+/** 
+ * Test the creation, approval and rejection of a loan reschedule request 
+ **/
+@SuppressWarnings({ "rawtypes" })
+public class LoanRescheduleRequestTest {
+	private ResponseSpecification responseSpec;
+	private ResponseSpecification generalResponseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private LoanRescheduleRequestHelper loanRescheduleRequestHelper;
+    private Integer clientId;
+    private Integer loanProductId;
+    private Integer loanId;
+    private Integer loanRescheduleRequestId;
+    private String loanPrincipalAmount = "100000.00";
+    private String numberOfRepayments = "12";
+    private String interestRatePerPeriod = "18";
+    private String dateString = "4 September 2014";
+    
+    @Before
+    public void initialize() {
+    	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.loanRescheduleRequestHelper = new LoanRescheduleRequestHelper(this.requestSpec, this.responseSpec);
+
+        this.generalResponseSpec = new ResponseSpecBuilder().build();
+        
+        // create all required entities
+        this.createRequiredEntities();
+    }
+    
+    /** 
+     * Creates the client, loan product, and loan entities 
+     **/
+    private void createRequiredEntities() {
+    	this.createClientEntity();
+    	this.createLoanProductEntity();
+    	this.createLoanEntity();
+    }
+    
+    /** 
+     * create a new client 
+     **/ 
+    private void createClientEntity() {
+    	this.clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+    	
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, this.clientId);
+    }
+    
+    /** 
+     * create a new loan product 
+     **/
+    private void createLoanProductEntity() {
+    	System.out.println("---------------------------------CREATING LOAN PRODUCT------------------------------------------");
+    	
+    	final String loanProductJSON = new LoanProductTestBuilder()
+    			.withPrincipal(loanPrincipalAmount)
+    			.withNumberOfRepayments(numberOfRepayments)
+    			.withinterestRatePerPeriod(interestRatePerPeriod)
+    			.withInterestRateFrequencyTypeAsYear()
+    			.build(null);
+    	
+    	this.loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+    	System.out.println("Successfully created loan product  (ID: " + this.loanProductId + ")");
+    }
+    
+    /** 
+     * submit a new loan application, approve and disburse the loan 
+     **/
+    private void createLoanEntity() {
+    	System.out.println("---------------------------------NEW LOAN APPLICATION------------------------------------------");
+    	
+    	final String loanApplicationJSON = new LoanApplicationTestBuilder()
+    			.withPrincipal(loanPrincipalAmount)
+    			.withLoanTermFrequency(numberOfRepayments)
+                .withLoanTermFrequencyAsMonths()
+                .withNumberOfRepayments(numberOfRepayments)
+                .withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths()
+                .withAmortizationTypeAsEqualInstallments()
+                .withInterestCalculationPeriodTypeAsDays()
+                .withInterestRatePerPeriod(interestRatePerPeriod)
+                .withLoanTermFrequencyAsMonths()
+                .withSubmittedOnDate(dateString)
+                .withExpectedDisbursementDate(dateString)
+                .withPrincipalGrace("2")
+                .withInterestGrace("2")
+    			.build(this.clientId.toString(), this.loanProductId.toString(), null);
+    	
+    	this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    	
+    	System.out.println("Sucessfully created loan (ID: " + this.loanId + ")");
+    	
+    	this.approveLoanApplication();
+    	this.disburseLoan();
+    }
+    
+    /** 
+     * approve the loan application 
+     **/
+    private void approveLoanApplication() {
+    	
+    	if(this.loanId != null) {
+    		this.loanTransactionHelper.approveLoan(this.dateString, this.loanId);
+    		System.out.println("Successfully approved loan (ID: " + this.loanId + ")");
+    	}
+    }
+    
+    /** 
+     * disburse the newly created loan 
+     **/
+    private void disburseLoan() {
+    	
+    	if(this.loanId != null) {
+    		this.loanTransactionHelper.disburseLoan(this.dateString, this.loanId);
+    		System.out.println("Successfully disbursed loan (ID: " + this.loanId + ")");
+    	}
+    }
+    
+    /** 
+     * create new loan reschedule request 
+     **/
+    private void createLoanRescheduleRequest() {
+    	System.out.println("---------------------------------CREATING LOAN RESCHEDULE REQUEST------------------------------------------");
+    	
+    	final String requestJSON = new LoanRescheduleRequestTestBuilder().build(this.loanId.toString());
+    	
+    	this.loanRescheduleRequestId = this.loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+    	this.loanRescheduleRequestHelper.verifyCreationOfLoanRescheduleRequest(this.loanRescheduleRequestId);
+    	
+    	System.out.println("Successfully created loan reschedule request (ID: " + this.loanRescheduleRequestId + ")");
+    }
+    
+    @Test
+    public void testCreateLoanRescheduleRequest() {
+    	this.createLoanRescheduleRequest();
+    }
+    
+    @Test
+    public void testRejectLoanRescheduleRequest() {
+    	this.createLoanRescheduleRequest();
+    	
+    	System.out.println("-----------------------------REJECTING LOAN RESCHEDULE REQUEST--------------------------");
+    	
+    	final String requestJSON = new LoanRescheduleRequestTestBuilder().getRejectLoanRescheduleRequestJSON();
+    	this.loanRescheduleRequestHelper.rejectLoanRescheduleRequest(this.loanRescheduleRequestId, requestJSON);
+    	
+    	final HashMap response = (HashMap) this.loanRescheduleRequestHelper.getLoanRescheduleRequest(loanRescheduleRequestId, "statusEnum");
+    	assertTrue((Boolean)response.get("rejected"));
+    	
+    	System.out.println("Successfully rejected loan reschedule request (ID: " + this.loanRescheduleRequestId + ")");
+    }
+    
+    @Test
+    public void testApproveLoanRescheduleRequest() {
+    	this.createLoanRescheduleRequest();
+    	
+    	System.out.println("-----------------------------APPROVING LOAN RESCHEDULE REQUEST--------------------------");
+    	
+    	final String requestJSON = new LoanRescheduleRequestTestBuilder().getApproveLoanRescheduleRequestJSON();
+    	this.loanRescheduleRequestHelper.approveLoanRescheduleRequest(this.loanRescheduleRequestId, requestJSON);
+    	
+    	final HashMap response = (HashMap) this.loanRescheduleRequestHelper.getLoanRescheduleRequest(loanRescheduleRequestId, "statusEnum");
+    	assertTrue((Boolean)response.get("approved"));
+    	
+    	final Integer numberOfRepayments = (Integer) this.loanTransactionHelper.getLoanDetail(requestSpec, generalResponseSpec, loanId, "numberOfRepayments");
+    	final HashMap loanSummary = this.loanTransactionHelper.getLoanSummary(requestSpec, generalResponseSpec, loanId);
+    	final Float totalExpectedRepayment = (Float) loanSummary.get("totalExpectedRepayment");
+    	
+    	assertEquals("NUMBER OF REPAYMENTS SHOULD BE 16, NOT 12", "16", numberOfRepayments.toString());
+    	assertEquals("TOTAL EXPECTED REPAYMENT MUST BE EQUAL TO 118000.0", "118000.0", totalExpectedRepayment.toString());
+    	
+    	System.out.println("Successfully approved loan reschedule request (ID: " + this.loanRescheduleRequestId + ")");
+    }
+}