fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From raj...@apache.org
Subject [1/3] incubator-fineract git commit: feature implementation of undoreject and undowithdrawal for client
Date Tue, 16 Aug 2016 10:57:46 GMT
Repository: incubator-fineract
Updated Branches:
  refs/heads/develop 961aa3df8 -> cc07999d6


feature implementation of undoreject and undowithdrawal for client


Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/58bbaa2e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/58bbaa2e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/58bbaa2e

Branch: refs/heads/develop
Commit: 58bbaa2e2b25a0aad984f1d276a21c4dd8fdd54b
Parents: 47f21bc
Author: jyothsnag <jyothsna@confluxtechnologies.com>
Authored: Fri Aug 12 15:44:07 2016 +0530
Committer: jyothsnag <jyothsna@confluxtechnologies.com>
Committed: Fri Aug 12 16:32:56 2016 +0530

----------------------------------------------------------------------
 api-docs/apiLive.htm                            |  92 +++++
 ...tUndoRejectAndWithdrawalIntegrationTest.java | 335 +++++++++++++++++++
 .../integrationtests/CurrenciesTest.java        |   2 +
 .../integrationtests/common/ClientHelper.java   | 204 ++++++++---
 .../commands/service/CommandWrapperBuilder.java |  16 +
 .../client/api/ClientApiConstants.java          |  12 +-
 .../client/api/ClientsApiResource.java          |  14 +-
 .../client/data/ClientDataValidator.java        |  49 +++
 .../portfolio/client/domain/Client.java         |  50 ++-
 .../handler/UndoRejectClientCommandHandler.java |  30 ++
 .../handler/UndoWithdrawalCommandHandler.java   |  30 ++
 .../service/ClientWritePlatformService.java     |   5 +
 ...ntWritePlatformServiceJpaRepositoryImpl.java |  57 +++-
 .../core_db/V318__client_undoreject.sql         |  25 ++
 14 files changed, 866 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/api-docs/apiLive.htm
----------------------------------------------------------------------
diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 4ab7a5c..6b15e12 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -222,6 +222,22 @@
 							</tr>
 							<tr>
 								<td></td>
+								<td>clients/{clientId}?command=UndoRejection</td>
+								<td><a href="#clients_UndoRejection">UndoReject a Client</a></td>
+								<td></td>
+								<td></td>
+								<td></td>
+							</tr>
+							<tr>
+								<td></td>
+								<td>clients/{clientId}?command=UndoWithdrawal</td>
+								<td><a href="#clients_UndoWithdrawal">UndoWithdrawal Client</a></td>
+								<td></td>
+								<td></td>
+								<td></td>
+							</tr>
+							<tr>
+								<td></td>
 								<td>clients/{clientId}?command=assignStaff</td>
 								<td><a href="#clients_assignStaff">Assign Staff</a></td>
 								<td></td>
@@ -4962,6 +4978,7 @@ Request Body:
 		<div class="method-example">
 	        <code class="method-declaration">POST https://Domain Name/api/v1/clients/{clientId}?command=reactivate</code>
 	        <code class="method-request">POST clients/1?command=reactivate
+
 Content-Type: application/json
 Request Body:
 {
@@ -4979,6 +4996,81 @@ Request Body:
 	        </code>
 	    </div>
 	</div>
+	
+	<a id="clients_UndoRejection" name="clients_UndoRejection" class="old-syle-anchor">&nbsp;</a>
+	<div class="method-section">
+	    <div class="method-description">
+	        <h4>UndoReject a Client</h4>
+	        <p>Clients can be reactivated after they have been rejected.</p>
+	        <p>Trying to reactivate a client in any other state throws an error.</p>
+	         <table class=matrixHeading>
+				<tr class="matrixHeadingBG">
+					<td><div class="fineractHeading2">Mandatory Fields</div></td>
+				</tr>
+				<tr class=alt>
+					<td>reopenedDate<br>
+					</td>
+				</tr>
+			</table>
+	    </div>
+		<div class="method-example">
+	        <code class="method-declaration">POST https://Domain Name/api/v1/clients/{clientId}?command=UndoRejection</code>
+	        <code class="method-request">POST clients/1?command=UndoRejection
+			
+Content-Type: application/json
+Request Body:
+{
+"reopenedDate":"28 November 2014",
+"locale":"en",
+"dateFormat":"dd MMMM yyyy"
+}
+			</code>
+	        <code class="method-response">
+{
+
+  "clientId":15,
+  "resourceId":15
+}
+	        </code>
+	    </div>
+	</div>
+			
+<a id="clients_UndoWithdrawal" name="clients_UndoWithdrawal" class="old-syle-anchor">&nbsp;</a>
+	<div class="method-section">
+	    <div class="method-description">
+	        <h4>UndoWithdraw a Client</h4>
+	        <p>Clients can be reactivated after they have been withdrawn.</p>
+	        <p>Trying to reactivate a client in any other state throws an error.</p>
+	         <table class=matrixHeading>
+				<tr class="matrixHeadingBG">
+					<td><div class="fineractHeading2">Mandatory Fields</div></td>
+				</tr>
+				<tr class=alt>
+					<td>reopenedDate<br>
+					</td>
+				</tr>
+			</table>
+	    </div>
+		<div class="method-example">
+	        <code class="method-declaration">POST https://Domain Name/api/v1/clients/{clientId}?command=UndoWithdrawal</code>
+	        <code class="method-request">POST clients/1?command=UndoWithdrawal
+Content-Type: application/json
+Request Body:
+{
+"reopenedDate":"28 November 2014",
+"locale":"en",
+"dateFormat":"dd MMMM yyyy"
+}
+			</code>
+	        <code class="method-response">
+{
+
+  "clientId":15,
+  "resourceId":15
+}
+	        </code>
+	    </div>
+	</div>
 		<a id="clients_assignStaff" name="clients_assignStaff" class="old-syle-anchor">&nbsp;</a>
 	<div class="method-section">
 	    <div class="method-description">

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java
new file mode 100644
index 0000000..af3b16b
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java
@@ -0,0 +1,335 @@
+package org.apache.fineract.integrationtests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Random;
+
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+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.LoanStatusChecker;
+import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
+import org.apache.fineract.portfolio.client.api.ClientApiConstants;
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.client.exception.InvalidClientStateTransitionException;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.joda.time.LocalDate;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+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({ "unused" })
+public class ClientUndoRejectAndWithdrawalIntegrationTest {
+
+	private static final String CREATE_CLIENT_URL = "/fineract-provider/api/v1/clients?" + Utils.TENANT_IDENTIFIER;
+	public static final String DATE_FORMAT = "dd MMMM yyyy";
+	private final String submittedOnDate = "submittedOnDate";
+	private final String officeId = "officeId";
+	private ResponseSpecification responseSpec;
+	private RequestSpecification requestSpec;
+	private ClientHelper clientHelper;
+
+	@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.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+	}
+
+	@Test
+	public void clientUndoRejectIntegrationTest() {
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.rejectClient(clientId);
+		ClientStatusChecker.verifyClientRejected(status);
+
+		status = this.clientHelper.undoReject(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@Test
+	public void testClientUndoRejectWithDateBeforeRejectDate() {
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.rejectClient(clientId);
+		ClientStatusChecker.verifyClientRejected(status);
+
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.undoRejectedclient(clientId,
+				CommonConstants.RESPONSE_ERROR, ClientHelper.CREATED_DATE);
+		assertEquals("error.msg.client.reopened.date.cannot.before.client.rejected.date",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+		status = this.clientHelper.undoReject(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Test
+	public void testClientUndoRejectWithoutReject() {
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+		ClientStatusChecker.verifyClientPending(status);
+
+		DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
+		Calendar todaysDate = Calendar.getInstance();
+		final String undoRejectDate = dateFormat.format(todaysDate.getTime());
+
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.undoRejectedclient(clientId,
+				CommonConstants.RESPONSE_ERROR, undoRejectDate);
+		assertEquals("error.msg.client.undorejection.on.nonrejected.account",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+		status = this.clientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@Test
+	public void testClientUndoRejectWithFutureDate() {
+
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.rejectClient(clientId);
+		ClientStatusChecker.verifyClientRejected(status);
+		DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
+		Calendar todaysDate = Calendar.getInstance();
+		todaysDate.add(Calendar.DATE, 1);
+		final String undoRejectDate = dateFormat.format(todaysDate.getTime());
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.undoWithdrawclient(clientId,
+				CommonConstants.RESPONSE_ERROR, undoRejectDate);
+		assertEquals("validation.msg.client.reopenedDate.is.greater.than.date",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+		status = this.clientHelper.undoReject(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@Test
+	public void clientUndoWithDrawnIntegrationTest() {
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.withdrawClient(clientId);
+		ClientStatusChecker.verifyClientWithdrawn(status);
+
+		status = this.clientHelper.undoWithdrawn(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@Test
+	public void testClientUndoWithDrawnWithDateBeforeWithdrawal() {
+
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.withdrawClient(clientId);
+		ClientStatusChecker.verifyClientWithdrawn(status);
+
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.undoWithdrawclient(clientId,
+				CommonConstants.RESPONSE_ERROR, ClientHelper.CREATED_DATE);
+		assertEquals("error.msg.client.reopened.date.cannot.before.client.withdrawal.date",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+		status = this.clientHelper.undoWithdrawn(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Test
+	public void testClientUndoWithDrawnWithoutWithdrawal() {
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
+		Calendar todaysDate = Calendar.getInstance();
+		final String undoWithdrawDate = dateFormat.format(todaysDate.getTime());
+
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.undoWithdrawclient(clientId,
+				CommonConstants.RESPONSE_ERROR, undoWithdrawDate);
+		assertEquals("error.msg.client.undoWithdrawal.on.nonwithdrawal.account",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+		status = this.clientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@Test
+	public void testClientUndoWithDrawnWithFutureDate() {
+
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.withdrawClient(clientId);
+		ClientStatusChecker.verifyClientWithdrawn(status);
+		DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
+		Calendar todaysDate = Calendar.getInstance();
+		todaysDate.add(Calendar.DATE, 1);
+		final String undoWithdrawDate = dateFormat.format(todaysDate.getTime());
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.undoWithdrawclient(clientId,
+				CommonConstants.RESPONSE_ERROR, undoWithdrawDate);
+		assertEquals("validation.msg.client.reopenedDate.is.greater.than.date",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+		status = this.clientHelper.undoWithdrawn(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Test
+	public void testValidateReopenedDate() {
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.withdrawClient(clientId);
+		ClientStatusChecker.verifyClientWithdrawn(status);
+		status = this.clientHelper.undoWithdrawn(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+		ArrayList<HashMap> clientErrorData = (ArrayList<HashMap>) validationErrorHelper.activateClient(clientId,
+				CommonConstants.RESPONSE_ERROR);
+		assertEquals("error.msg.clients.submittedOnDate.after.reopened.date",
+				((HashMap<String, Object>) clientErrorData.get(0)).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+
+	}
+
+	@Test
+	public void testReopenedDate() {
+		final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
+		final ClientHelper validationErrorHelper = new ClientHelper(this.requestSpec, errorResponse);
+
+		// CREATE CLIENT
+		this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
+		final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec);
+		Assert.assertNotNull(clientId);
+		// GET CLIENT STATUS
+		HashMap<String, Object> status = ClientHelper.getClientStatus(requestSpec, responseSpec,
+				String.valueOf(clientId));
+		ClientStatusChecker.verifyClientPending(status);
+
+		status = this.clientHelper.withdrawClient(clientId);
+		ClientStatusChecker.verifyClientWithdrawn(status);
+		status = this.clientHelper.undoWithdrawn(clientId);
+		ClientStatusChecker.verifyClientPending(status);
+		status = this.clientHelper.activateClientWithDiffDateOption(clientId, ClientHelper.CREATED_DATE_PLUS_TWO);
+
+	}
+
+	private static String randomIDGenerator(final String prefix, final int lenOfRandomSuffix) {
+		return Utils.randomStringGenerator(prefix, lenOfRandomSuffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/CurrenciesTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/CurrenciesTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/CurrenciesTest.java
index a418c4c..001486f 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/CurrenciesTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/CurrenciesTest.java
@@ -73,6 +73,8 @@ public class CurrenciesTest {
         currenciestoUpdate.add("LBP");
         currenciestoUpdate.add("GHC");
         currenciestoUpdate.add("USD");
+        currenciestoUpdate.add("INR");
+
 
         ArrayList<String> currenciesOutput = CurrenciesHelper.updateSelectedCurrencies(this.requestSpec, this.responseSpec,
                 currenciestoUpdate);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
index fa46249..ec6ea52 100755
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
@@ -20,6 +20,7 @@ package org.apache.fineract.integrationtests.common;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 
 import org.apache.fineract.infrastructure.codes.domain.CodeValue;
@@ -41,13 +42,18 @@ public class ClientHelper {
     private static final String REJECT_CLIENT_COMMAND = "reject";
     private static final String ACTIVATE_CLIENT_COMMAND = "activate";
     private static final String WITHDRAW_CLIENT_COMMAND = "withdraw";
+    private static final String UNDOREJECT_CLIENT_COMMAND = "undoRejection";
+    private static final String UNDOWITHDRAWN_CLIENT_COMMAND = "undoWithdrawal";
 
     public static final String CREATED_DATE = "27 November 2014";
     public static final String CREATED_DATE_PLUS_ONE = "28 November 2014";
+    public static final String CREATED_DATE_PLUS_TWO = "29 November 2014";
+
     public static final String CREATED_DATE_MINUS_ONE = "27 November 2014";
     public static final String TRANSACTION_DATE = "01 March 2013";
     public static final String LAST_TRANSACTION_DATE = "01 March 2013";
     public static final String DATE_FORMAT = "dd MMMM yyyy";
+    
 
     public ClientHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
         this.requestSpec = requestSpec;
@@ -70,6 +76,26 @@ public class ClientHelper {
                 "clientId");
     }
     
+    
+    
+    public static Integer createClientPending(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
+        return createClientPending(requestSpec, responseSpec, "04 March 2014");
+    }
+
+    public static Integer createClientPending(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+            final String submittedOnDate) {
+        return createClientPending(requestSpec, responseSpec, submittedOnDate, "1");
+    }
+
+    public static Integer createClientPending(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+            final String submittedOnDate, final String officeId) {
+        System.out.println("---------------------------------CREATING A CLIENT IN PENDING---------------------------------------------");
+        return Utils.performServerPost(requestSpec, responseSpec, CREATE_CLIENT_URL, getTestClientAsJSONPending(submittedOnDate, officeId),
+                "clientId");
+    }
+   
+    
+    
     public static Integer createClientAsPerson(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
         return createClientAsPerson(requestSpec, responseSpec, "04 March 2011");
     }
@@ -138,13 +164,30 @@ public class ClientHelper {
         map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
         map.put("externalId", randomIDGenerator("ID_", 7));
         map.put("dateFormat", DATE_FORMAT);
-        map.put("locale", "en");
-        map.put("active", "true");
-        map.put("activationDate", dateOfJoining);
-        System.out.println("map : " + map);
-        return new Gson().toJson(map);
+		map.put("locale", "en");
+		map.put("active", "true");
+		map.put("activationDate", dateOfJoining);
+		System.out.println("map : " + map);
+		return new Gson().toJson(map);
+    }
+    
+    public static String getTestClientAsJSONPending(final String submittedOnDate, final String officeId) {
+        final HashMap<String, String> map = new HashMap<>();
+        map.put("officeId", officeId);
+        map.put("firstname", Utils.randomNameGenerator("Client_FirstName_", 5));
+        map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
+        map.put("externalId", randomIDGenerator("ID_", 7));
+        map.put("dateFormat", DATE_FORMAT);
+		map.put("locale", "en");
+		map.put("active", "false");
+		map.put("submittedOnDate", submittedOnDate);
+		System.out.println("map : " + map);
+		return new Gson().toJson(map);
     }
     
+    
+    
+    
     public static String getTestPersonClientAsJSON(final String dateOfJoining, final String officeId) {
         final HashMap<String, Object> map = new HashMap<>();
         map.put("officeId", officeId);
@@ -251,49 +294,72 @@ public class ClientHelper {
 
     }
 
-    private String getReactivateClientAsJSON() {
+	private String getReactivateClientAsJSON() {
+		final HashMap<String, String> map = new HashMap<>();
+		map.put("locale", CommonConstants.locale);
+		map.put("dateFormat", CommonConstants.dateFormat);
+		map.put("reactivationDate", CREATED_DATE_PLUS_ONE);
+		String clientJson = new Gson().toJson(map);
+		System.out.println(clientJson);
+		return clientJson;
+
+	}
+
+	private String getUndoRejectClientAsJSON(final String date) {
+		final HashMap<String, String> map = new HashMap<>();
+		map.put("locale", CommonConstants.locale);
+		map.put("dateFormat", CommonConstants.dateFormat);
+		map.put("reopenedDate", date);
+		String clientJson = new Gson().toJson(map);
+		System.out.println(clientJson);
+		return clientJson;
+
+	}
+
+	private String getUndoWithdrawnClientAsJSON(final String date) {
+		final HashMap<String, String> map = new HashMap<>();
+		map.put("locale", CommonConstants.locale);
+		map.put("dateFormat", CommonConstants.dateFormat);
+		map.put("reopenedDate", date);
+		String clientJson = new Gson().toJson(map);
+		System.out.println(clientJson);
+		return clientJson;
+
+	}
+
+	private String getRejectClientAsJSON() {
+		final HashMap<String, String> map = new HashMap<>();
+		/* Retrieve Code id for the Code "ClientRejectReason" */
+		String codeName = "ClientRejectReason";
+		HashMap<String, Object> code = CodeHelper.getCodeByName(this.requestSpec, this.responseSpec, codeName);
+		Integer clientRejectionReasonCodeId = (Integer) code.get("id");
+
+		/* Retrieve/Create Code Values for the Code "ClientRejectReason" */
+		HashMap<String, Object> codeValue = CodeHelper.retrieveOrCreateCodeValue(clientRejectionReasonCodeId,
+				this.requestSpec, this.responseSpec);
+		Integer rejectionReasonId = (Integer) codeValue.get("id");
+
+		map.put("locale", CommonConstants.locale);
+		map.put("dateFormat", CommonConstants.dateFormat);
+		map.put("rejectionDate", CREATED_DATE_PLUS_ONE);
+		map.put("rejectionReasonId", rejectionReasonId.toString());
+		String clientJson = new Gson().toJson(map);
+		System.out.println(clientJson);
+		return clientJson;
+
+	}
+
+    private String getActivateClientAsJSON(String date) {
         final HashMap<String, String> map = new HashMap<>();
         map.put("locale", CommonConstants.locale);
         map.put("dateFormat", CommonConstants.dateFormat);
-        map.put("reactivationDate", CREATED_DATE_PLUS_ONE);
+        map.put("activationDate", date);
         String clientJson = new Gson().toJson(map);
         System.out.println(clientJson);
         return clientJson;
-
-    }
-
-    private String getRejectClientAsJSON() {
-        final HashMap<String, String> map = new HashMap<>();
-        /* Retrieve Code id for the Code "ClientRejectReason" */
-        String codeName = "ClientRejectReason";
-        HashMap<String, Object> code = CodeHelper.getCodeByName(this.requestSpec, this.responseSpec, codeName);
-        Integer clientRejectionReasonCodeId = (Integer) code.get("id");
-
-        /* Retrieve/Create Code Values for the Code "ClientRejectReason" */
-        HashMap<String, Object> codeValue = CodeHelper.retrieveOrCreateCodeValue(clientRejectionReasonCodeId, this.requestSpec,
-                this.responseSpec);
-        Integer rejectionReasonId = (Integer) codeValue.get("id");
-
-        map.put("locale", CommonConstants.locale);
-        map.put("dateFormat", CommonConstants.dateFormat);
-        map.put("rejectionDate", CREATED_DATE_PLUS_ONE);
-        map.put("rejectionReasonId", rejectionReasonId.toString());
-        String clientJson = new Gson().toJson(map);
-        System.out.println(clientJson);
-        return clientJson;
-
-    }
-
-    private String getActivateClientAsJSON() {
-        final HashMap<String, String> map = new HashMap<>();
-        map.put("locale", CommonConstants.locale);
-        map.put("dateFormat", CommonConstants.dateFormat);
-        map.put("activationDate", CREATED_DATE_PLUS_ONE);
-        String clientJson = new Gson().toJson(map);
-        System.out.println(clientJson);
-        return clientJson;
-
     }
+    
+    
 
     private String getWithdrawClientAsJSON() {
         final HashMap<String, String> map = new HashMap<>();
@@ -366,7 +432,7 @@ public class ClientHelper {
 
     public HashMap<String, Object> activateClient(final Integer clientId) {
         System.out.println("--------------------------------- ACTIVATE CLIENT -------------------------------");
-        return performClientActions(createClientOperationURL(ACTIVATE_CLIENT_COMMAND, clientId), getActivateClientAsJSON(), clientId);
+        return performClientActions(createClientOperationURL(ACTIVATE_CLIENT_COMMAND, clientId), getActivateClientAsJSON(CREATED_DATE_PLUS_ONE), clientId);
     }
 
     public HashMap<String, Object> withdrawClient(final Integer clientId) {
@@ -374,10 +440,56 @@ public class ClientHelper {
         return performClientActions(createClientOperationURL(WITHDRAW_CLIENT_COMMAND, clientId), getWithdrawClientAsJSON(), clientId);
     }
 
-    private String createClientOperationURL(final String command, final Integer clientId) {
-        return CLIENT_URL + "/" + clientId + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
-    }
-
+	private String createClientOperationURL(final String command, final Integer clientId) {
+		return CLIENT_URL + "/" + clientId + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
+	}
+
+	public HashMap<String, Object> undoReject(final Integer clientId) {
+		System.out.println("--------------------------------- UNDO REJECT CLIENT -------------------------------");
+		return performClientActions(createClientOperationURL(UNDOREJECT_CLIENT_COMMAND, clientId),
+				getUndoRejectClientAsJSON(CREATED_DATE_PLUS_TWO), clientId);
+	}
+
+	public HashMap<String, Object> undoWithdrawn(final Integer clientId) {
+		System.out.println("--------------------------------- UNDO WITHDRAWN CLIENT -------------------------------");
+		return performClientActions(createClientOperationURL(UNDOWITHDRAWN_CLIENT_COMMAND, clientId),
+				getUndoWithdrawnClientAsJSON(CREATED_DATE_PLUS_TWO), clientId);
+	}
+
+	public Object undoRejectedclient(final Integer clientId, final String jsonAttributeToGetBack,
+			final String rejectedDate) {
+		System.out.println("----------------------------------UNDO REJECT CLIENT ----------------------------------");
+		return performClientActionsWithValidationErrors(createClientOperationURL(UNDOREJECT_CLIENT_COMMAND, clientId),
+				getUndoRejectClientAsJSON(rejectedDate), jsonAttributeToGetBack);
+	}
+
+	public Object undoWithdrawclient(final Integer clientId, final String jsonAttributeToGetBack,
+			final String rejectedDate) {
+		System.out.println("----------------------------------UNDO WITHDRAW CLIENT ----------------------------------");
+		return performClientActionsWithValidationErrors(
+				createClientOperationURL(UNDOWITHDRAWN_CLIENT_COMMAND, clientId),
+				getUndoWithdrawnClientAsJSON(rejectedDate), jsonAttributeToGetBack);
+	}
+
+	public Object activateClient(final Integer clientId, final String jsonAttributeToGetBack) {
+		System.out.println("--------------------------------- ACTIVATE CLIENT -------------------------------");
+		return performClientActionsWithValidationErrors(createClientOperationURL(ACTIVATE_CLIENT_COMMAND, clientId),
+				getActivateClientAsJSON(CREATED_DATE_PLUS_ONE), jsonAttributeToGetBack);
+	}
+
+	public HashMap<String, Object> activateClientWithDiffDateOption(final Integer clientId,
+			final String activationDate) {
+		System.out.println("--------------------------------- ACTIVATE CLIENT -------------------------------");
+		return performClientActions(createClientOperationURL(ACTIVATE_CLIENT_COMMAND, clientId),
+				getActivateClientAsJSON(activationDate), clientId);
+	}
+
+	private ArrayList<HashMap> performClientActionsWithValidationErrors(final String postURLForClient,
+			final String jsonToBeSent, final String jsonAttributeToGetBack) {
+		return Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForClient, jsonToBeSent,
+				jsonAttributeToGetBack);
+	}
+    
     private HashMap<String, Object> performClientActions(final String postURLForClient, final String jsonToBeSent, final Integer clientId) {
         Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForClient, jsonToBeSent, CommonConstants.RESPONSE_STATUS);
         HashMap<String, Object> response = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId));

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index 2d678b1..fa408d6 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -582,6 +582,22 @@ public class CommandWrapperBuilder {
         this.json = json;
         return this;
     }
+    public CommandWrapperBuilder undoRejection(final Long clientId) {
+        this.actionName = "UNDOREJECT";
+        this.entityName = "CLIENT";
+        this.entityId = clientId;
+        this.clientId = clientId;
+        this.href = "/clients/" + clientId + "?command=undoRejection";
+        return this;
+    }
+    public CommandWrapperBuilder undoWithdrawal(final Long clientId) {
+        this.actionName = "UNDOWITHDRAWAL";
+        this.entityName = "CLIENT";
+        this.entityId = clientId;
+        this.clientId = clientId;
+        this.href = "/clients/" + clientId + "?command=undoWithdrawal";
+        return this;
+    }
 
     public CommandWrapperBuilder createDatatable(final String datatable, final Long apptableId, final Long datatableId) {
         this.actionName = "CREATE";

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
index fb07c0e..e4f3ef1 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
@@ -91,6 +91,8 @@ public class ClientApiConstants {
     public static final String staffIdParamName = "staffId";
     public static final String closureDateParamName = "closureDate";
     public static final String closureReasonIdParamName = "closureReasonId";
+    public static final String reopenedDateParamName = "reopenedDate";
+
 
     public static final String rejectionDateParamName = "rejectionDate";
     public static final String rejectionReasonIdParamName = "rejectionReasonId";
@@ -221,8 +223,14 @@ public class ClientApiConstants {
     public static final Set<String> CLIENT_REJECT_DATA_PARAMETERS = new HashSet<>(
             Arrays.asList(localeParamName, dateFormatParamName, rejectionDateParamName, rejectionReasonIdParamName));
 
-    public static final Set<String> CLIENT_WITHDRAW_DATA_PARAMETERS = new HashSet<>(
-            Arrays.asList(localeParamName, dateFormatParamName, withdrawalDateParamName, withdrawalReasonIdParamName));
+	public static final Set<String> CLIENT_WITHDRAW_DATA_PARAMETERS = new HashSet<>(
+			Arrays.asList(localeParamName, dateFormatParamName, withdrawalDateParamName, withdrawalReasonIdParamName));
+	
+	public static final Set<String> UNDOREJECTION_REQUEST_DATA_PARAMETERS = new HashSet<>(
+			Arrays.asList(localeParamName, dateFormatParamName, reopenedDateParamName));
+	
+	public static final Set<String> UNDOWITHDRAWN_REQUEST_DATA_PARAMETERS = new HashSet<>(
+			Arrays.asList(localeParamName, dateFormatParamName, reopenedDateParamName));
 
     public static final Set<String> CLIENT_CHARGES_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(chargeIdParamName,
             clientIdParamName, chargeNameParamName, penaltyParamName, chargeTimeTypeParamName, dueAsOfDateParamName,

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
index c464470..f8bf7a8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
@@ -273,10 +273,16 @@ public class ClientsApiResource {
         } else if (is(commandParam, "withdraw")) {
             commandRequest = builder.withdrawClient(clientId).build();
             result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
-        } else if (is(commandParam, "reactivate")) {
-            commandRequest = builder.reActivateClient(clientId).build();
-            result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
-        }
+		} else if (is(commandParam, "reactivate")) {
+			commandRequest = builder.reActivateClient(clientId).build();
+			result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+		} else if (is(commandParam, "undoRejection")) {
+			commandRequest = builder.undoRejection(clientId).build();
+			result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+		} else if (is(commandParam, "undoWithdrawal")) {
+			commandRequest = builder.undoWithdrawal(clientId).build();
+			result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+		}
 
         if (result == null) { throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate",
                 "unassignStaff", "assignStaff", "close", "proposeTransfer", "withdrawTransfer", "acceptTransfer", "rejectTransfer",

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
index 3ddf911..6634916 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
@@ -720,4 +720,53 @@ public final class ClientDataValidator {
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
 
     }
+    
+    
+    public void validateUndoRejection(final JsonCommand command) {
+
+        final String json = command.json();
+
+        if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
+
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.UNDOREJECTION_REQUEST_DATA_PARAMETERS);
+
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
+                .resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
+
+        final JsonElement element = command.parsedJson();
+
+        final LocalDate undoRejectionDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.reopenedDateParamName,
+                element);
+		baseDataValidator.reset().parameter(ClientApiConstants.reopenedDateParamName).value(undoRejectionDate).notNull()
+				.validateDateBeforeOrEqual(DateUtils.getLocalDateOfTenant());
+
+        throwExceptionIfValidationWarningsExist(dataValidationErrors);
+
+    }
+    public void validateUndoWithDrawn(final JsonCommand command) {
+
+        final String json = command.json();
+
+        if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
+
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.UNDOWITHDRAWN_REQUEST_DATA_PARAMETERS);
+
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
+                .resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
+
+        final JsonElement element = command.parsedJson();
+
+        final LocalDate undoWithdrawnDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.reopenedDateParamName,
+                element);
+		baseDataValidator.reset().parameter(ClientApiConstants.reopenedDateParamName).value(undoWithdrawnDate).notNull()
+				.validateDateBeforeOrEqual(DateUtils.getLocalDateOfTenant());
+
+        throwExceptionIfValidationWarningsExist(dataValidationErrors);
+
+    }
+    
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
index 96aafba..5210f18 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
@@ -222,6 +222,14 @@ public final class Client extends AbstractPersistable<Long> {
     @Column(name = "legal_form_enum", nullable = true)
     private Integer legalForm;
 
+	@Column(name = "reopened_on_date", nullable = true)
+	@Temporal(TemporalType.DATE)
+	private Date reopenedDate;
+
+	@ManyToOne(optional = true)
+	@JoinColumn(name = "reopened_by_userid", nullable = true)
+	private AppUser reopenedBy;
+
     public static Client createNew(final AppUser currentUser, final Office clientOffice, final Group clientParentGroup, final Staff staff,
             final SavingsProduct savingsProduct, final CodeValue gender, final CodeValue clientType, final CodeValue clientClassification,
             final Integer legalForm, final JsonCommand command) {
@@ -453,7 +461,15 @@ public final class Client extends AbstractPersistable<Long> {
     private boolean isDateInTheFuture(final LocalDate localDate) {
         return localDate.isAfter(DateUtils.getLocalDateOfTenant());
     }
-
+    
+    public boolean isRejected() {
+        return ClientStatus.fromInt(this.status).isRejected();
+    }
+    
+    public boolean isWithdrawn() {
+        return ClientStatus.fromInt(this.status).isWithdrawn();
+    }
+    
     public Map<String, Object> update(final JsonCommand command) {
 
         final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
@@ -644,6 +660,17 @@ public final class Client extends AbstractPersistable<Long> {
             dataValidationErrors.add(error);
         }
 
+		if (getReopenedDate() != null && getActivationLocalDate() != null
+				&& getReopenedDate().isAfter(getActivationLocalDate())) {
+
+			final String defaultUserMessage = "reopened date cannot be after the submittedon date";
+			final ApiParameterError error = ApiParameterError.parameterError(
+					"error.msg.clients.submittedOnDate.after.reopened.date", defaultUserMessage,
+					ClientApiConstants.reopenedDateParamName, this.reopenedDate);
+
+			dataValidationErrors.add(error);
+		}
+
         if (getActivationLocalDate() != null && isDateInTheFuture(getActivationLocalDate())) {
 
             final String defaultUserMessage = "Activation date cannot be in the future.";
@@ -891,8 +918,18 @@ public final class Client extends AbstractPersistable<Long> {
     public LocalDate getClosureDate() {
         return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.closureDate), null);
     }
+    public LocalDate getRejectedDate() {
+        return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.rejectionDate), null);
+    }
+    public LocalDate getWithdrawalDate() {
+        return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.withdrawalDate), null);
+	}
 
-    public CodeValue gender() {
+	public LocalDate getReopenedDate() {
+		return this.reopenedDate == null ? null : new LocalDate(this.reopenedDate);
+	}
+
+	public CodeValue gender() {
         return this.gender;
     }
 
@@ -958,6 +995,15 @@ public final class Client extends AbstractPersistable<Long> {
         this.status = ClientStatus.PENDING.getValue();
 
     }
+    
+	public void reOpened(AppUser currentUser, Date reopenedDate) {
+		this.reopenedDate = reopenedDate;
+		this.reopenedBy = currentUser;
+		this.updatedBy = currentUser;
+		this.updatedOnDate = reopenedDate;
+		this.status = ClientStatus.PENDING.getValue();
+
+	}
 
 	public Integer getLegalForm() {
 		return legalForm;

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoRejectClientCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoRejectClientCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoRejectClientCommandHandler.java
new file mode 100644
index 0000000..2dee42e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoRejectClientCommandHandler.java
@@ -0,0 +1,30 @@
+package org.apache.fineract.portfolio.client.handler;
+
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.client.service.ClientWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = "CLIENT", action = "UNDOREJECT")
+public class UndoRejectClientCommandHandler implements NewCommandSourceHandler {
+
+	 private final ClientWritePlatformService clientWritePlatformService;
+
+	    @Autowired
+	    public UndoRejectClientCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
+	        this.clientWritePlatformService = clientWritePlatformService;
+	    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult processCommand(final JsonCommand command) {
+
+        return this.clientWritePlatformService.undoRejection(command.entityId(), command);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoWithdrawalCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoWithdrawalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoWithdrawalCommandHandler.java
new file mode 100644
index 0000000..a3c9163
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UndoWithdrawalCommandHandler.java
@@ -0,0 +1,30 @@
+package org.apache.fineract.portfolio.client.handler;
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.client.service.ClientWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = "CLIENT", action = "UNDOWITHDRAWAL")
+public class UndoWithdrawalCommandHandler implements NewCommandSourceHandler {
+
+	 private final ClientWritePlatformService clientWritePlatformService;
+
+	    @Autowired
+	    public UndoWithdrawalCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
+	        this.clientWritePlatformService = clientWritePlatformService;
+	    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult processCommand(final JsonCommand command) {
+
+        return this.clientWritePlatformService.undoWithdrawal(command.entityId(), command);
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformService.java
index 30f7213..c520aff 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformService.java
@@ -45,4 +45,9 @@ public interface ClientWritePlatformService {
 
     CommandProcessingResult reActivateClient(Long entityId, JsonCommand command);
 
+	CommandProcessingResult undoRejection(Long entityId, JsonCommand command);
+	
+	CommandProcessingResult undoWithdrawal(Long entityId, JsonCommand command);
+
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
index 038c46d..5781082 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
@@ -844,4 +844,59 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
                 .withEntityId(entityId) //
                 .build();
     }
-}
\ No newline at end of file
+
+	@Override
+	public CommandProcessingResult undoRejection(Long entityId, JsonCommand command) {
+		final AppUser currentUser = this.context.authenticatedUser();
+		this.fromApiJsonDeserializer.validateUndoRejection(command);
+
+		final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId);
+		final LocalDate undoRejectDate = command
+				.localDateValueOfParameterNamed(ClientApiConstants.reopenedDateParamName);
+
+		if (!client.isRejected()) {
+			final String errorMessage = "only rejected clients may be reactivated.";
+			throw new InvalidClientStateTransitionException("undorejection", "on.nonrejected.account", errorMessage);
+		} else if (client.getRejectedDate().isAfter(undoRejectDate)) {
+			final String errorMessage = "The client reactivation date cannot be before the client rejected date.";
+			throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.rejected.date",
+					errorMessage, undoRejectDate, client.getRejectedDate());
+		}
+
+		client.reOpened(currentUser, undoRejectDate.toDate());
+		this.clientRepository.saveAndFlush(client);
+
+		return new CommandProcessingResultBuilder() //
+				.withCommandId(command.commandId()) //
+				.withClientId(entityId) //
+				.withEntityId(entityId) //
+				.build();
+	}
+
+	@Override
+	public CommandProcessingResult undoWithdrawal(Long entityId, JsonCommand command) {
+		final AppUser currentUser = this.context.authenticatedUser();
+		this.fromApiJsonDeserializer.validateUndoWithDrawn(command);
+
+		final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId);
+		final LocalDate undoWithdrawalDate = command
+				.localDateValueOfParameterNamed(ClientApiConstants.reopenedDateParamName);
+
+		if (!client.isWithdrawn()) {
+			final String errorMessage = "only withdrawal clients may be reactivated.";
+			throw new InvalidClientStateTransitionException("undoWithdrawal", "on.nonwithdrawal.account", errorMessage);
+		} else if (client.getWithdrawalDate().isAfter(undoWithdrawalDate)) {
+			final String errorMessage = "The client reactivation date cannot be before the client withdrawal date.";
+			throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.withdrawal.date",
+					errorMessage, undoWithdrawalDate, client.getWithdrawalDate());
+		}
+		client.reOpened(currentUser, undoWithdrawalDate.toDate());
+		this.clientRepository.saveAndFlush(client);
+
+		return new CommandProcessingResultBuilder() //
+				.withCommandId(command.commandId()) //
+				.withClientId(entityId) //
+				.withEntityId(entityId) //
+				.build();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/58bbaa2e/fineract-provider/src/main/resources/sql/migrations/core_db/V318__client_undoreject.sql
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V318__client_undoreject.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V318__client_undoreject.sql
new file mode 100644
index 0000000..6f3cccd
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V318__client_undoreject.sql
@@ -0,0 +1,25 @@
+--
+-- 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.
+--
+
+ALTER TABLE `m_client`
+	ADD COLUMN `reopened_on_date` DATE NULL AFTER `legal_form_enum`,
+	ADD COLUMN `reopened_by_userid` BIGINT NULL AFTER `reopened_on_date`;
+	
+INSERT INTO `m_permission` ( `grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNDOREJECT_CLIENT', 'CLIENT', 'UNDOREJECT', 1),
+('portfolio', 'UNDOREJECT_CLIENT_CHECKER', 'CLIENT', 'UNDOREJECT_CHECKER', 1),('portfolio', 'UNDOWITHDRAWAL_CLIENT', 'CLIENT', 'UNDOWITHDRAWAL', 1),('portfolio', 'UNDOWITHDRAWAL_CLIENT_CHECKER', 'CLIENT', 'UNDOWITHDRAWAL_CHECKER', 1);


Mime
View raw message