diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 16e6ab529..10e09884e 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -193,6 +193,30 @@ + + + clients/{clientId}?command=reject + Reject a Client + + + + + + + clients/{clientId}?command=withdraw + Withdraw a Client + + + + + + + clients/{clientId}?command=reactivate + Reactivate a Client + + + + clients/{clientId}?command=assignStaff @@ -3500,6 +3524,91 @@ Request Body: +   +
+
+

Reject a Client

+

Clients can be rejected when client is in pending status. This API exists to reject a client .

+

If the client is any other status results in error.

+
+
+ POST https://Domain Name/api/v1/clients/{clientId}?command=reject + POST clients/1?command=reject +Content-Type: application/json +Request Body: +{ +"rejectDate":"28 November 2014", +"rejectReasonId":16, +"locale":"en", +"dateFormat":"dd MMMM yyyy" +} + + +{ + "clientId":15, + "resourceId":15 +} + +
+
+ +   +
+
+

Withdraw a Client

+

Clients can be withdrawn when client is in pending status. This API exists to withdraw a client .

+

If the client is any other status results in error.

+
+
+ POST https://Domain Name/api/v1/clients/{clientId}?command=withdraw + POST clients/1?command=withdraw +Content-Type: application/json +Request Body: +{ +"withdrawDate":"28 November 2014", +"withdrawReasonId":17, +"locale":"en", +"dateFormat":"dd MMMM yyyy" +} + + +{ + "officeId":1, + "clientId":15, + "resourceId":15 +} + +
+
+ + +   +
+
+

Reactivating a Client

+

Clients can be reactivated when client is in closed status. This API exists to reactivate a client .

+

If the client is any other status results in error.

+
+
+ POST https://Domain Name/api/v1/clients/{clientId}?command=reactivate + POST clients/1?command=reactivate +Content-Type: application/json +Request Body: +{ +"reactivationDate":"28 November 2014", +"locale":"en", +"dateFormat":"dd MMMM yyyy" +} + + +{ + + "clientId":15, + "resourceId":15 +} + +
+
 
diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java index 7c66482c9..28456cf28 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java @@ -87,8 +87,7 @@ public class ClientLoanIntegrationTest { ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); final Integer loanProductID = createLoanProduct(false, NONE); final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00"); - final ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, - loanID); + final ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec,loanID); verifyLoanRepaymentSchedule(loanSchedule); } diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientStatusChecker.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientStatusChecker.java new file mode 100644 index 000000000..5b1017105 --- /dev/null +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientStatusChecker.java @@ -0,0 +1,48 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.integrationtests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +public class ClientStatusChecker { + public static void verifyClientIsActive(final HashMap clientStatusHashMap) { + assertEquals((int) clientStatusHashMap.get("id"), 300); + } + + + public static void verifyClientClosed(final HashMap clientStatusHashMap) { + System.out.println("\n-------------------------------------- VERIFYING CLIENT IS CLOSED ------------------------------------"); + assertEquals((int) clientStatusHashMap.get("id"), 600); + System.out.println("Client Status:" + clientStatusHashMap + "\n"); + } + public static void verifyClientPending(final HashMap clientStatusHashMap) { + System.out.println("\n-------------------------------------- VERIFYING CLIENT IS PENDING ------------------------------------"); + assertEquals((int) clientStatusHashMap.get("id"), 100); + System.out.println("Client Status:" + clientStatusHashMap + "\n"); + } + public static void verifyClientRejected(final HashMap clientStatusHashMap) { + System.out.println("\n-------------------------------------- VERIFYING CLIENT IS REJECTED ------------------------------------"); + assertEquals((int) clientStatusHashMap.get("id"), 700); + System.out.println("Client Status:" + clientStatusHashMap + "\n"); + } + + public static void verifyClientActiavted(final HashMap clientStatusHashMap) { + System.out.println("\n-------------------------------------- VERIFYING CLIENT IS ACTIVATED ------------------------------------"); + assertEquals((int) clientStatusHashMap.get("id"), 300); + System.out.println("Client Status:" + clientStatusHashMap + "\n"); + } + + public static void verifyClientWithdrawn(final HashMap clientStatusHashMap) { + System.out.println("\n-------------------------------------- VERIFYING CLIENT IS WITHDRAWN ------------------------------------"); + assertEquals((int) clientStatusHashMap.get("id"), 800); + System.out.println("Client Status:" + clientStatusHashMap + "\n"); + } + + +} diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java new file mode 100644 index 000000000..96fa5c580 --- /dev/null +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java @@ -0,0 +1,78 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.integrationtests; + +import java.util.HashMap; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mifosplatform.integrationtests.common.ClientHelper; +import org.mifosplatform.integrationtests.common.SchedulerJobHelper; +import org.mifosplatform.integrationtests.common.Utils; +import org.mifosplatform.integrationtests.common.accounting.AccountHelper; +import org.mifosplatform.integrationtests.common.accounting.JournalEntryHelper; +import org.mifosplatform.integrationtests.common.accounting.PeriodicAccrualAccountingHelper; +import org.mifosplatform.integrationtests.common.loans.LoanTransactionHelper; +import org.mifosplatform.integrationtests.common.savings.SavingsAccountHelper; +import org.mifosplatform.integrationtests.common.savings.SavingsStatusChecker; + +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; + +public class ClientTest { + + 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(); + + } + + @Test + public void testClientStatus() { + this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); + final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); + ClientStatusChecker.verifyClientIsActive(status); + + HashMap clientStatusHashMap = this.clientHelper.closeClient(clientId); + ClientStatusChecker.verifyClientClosed(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.reactivateClient(clientId); + ClientStatusChecker.verifyClientPending(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.rejectClient(clientId); + ClientStatusChecker.verifyClientRejected(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.activateClient(clientId); + ClientStatusChecker.verifyClientActiavted(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.closeClient(clientId); + ClientStatusChecker.verifyClientClosed(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.reactivateClient(clientId); + ClientStatusChecker.verifyClientPending(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.withdrawClient(clientId); + ClientStatusChecker.verifyClientWithdrawn(clientStatusHashMap); + + + + } + +} diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java index 80fab5744..66d2b5e89 100755 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java @@ -15,7 +15,27 @@ import com.jayway.restassured.specification.ResponseSpecification; public class ClientHelper { + private final RequestSpecification requestSpec; + private final ResponseSpecification responseSpec; + private static final String CREATE_CLIENT_URL = "/mifosng-provider/api/v1/clients?" + Utils.TENANT_IDENTIFIER; + private static final String CLIENT_URL = "/mifosng-provider/api/v1/clients"; + private static final String CLOSE_CLIENT_COMMAND = "close"; + private static final String REACTIVATE_CLIENT_COMMAND = "reactivate"; + private static final String REJECT_CLIENT_COMMAND = "reject"; + private static final String ACTIVATE_CLIENT_COMMAND ="activate"; + private static final String WITHDRAW_CLIENT_COMMAND = "withdraw"; + + 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_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 ClientHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + this.requestSpec = requestSpec; + this.responseSpec = responseSpec; + } public static Integer createClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { return createClient(requestSpec, responseSpec, "04 March 2011"); @@ -34,21 +54,16 @@ public class ClientHelper { } public static Object assignStaffToClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, - final String clientId, final String staffId) { - final String CLIENT_ASSIGN_STAFF_URL = "/mifosng-provider/api/v1/clients/" + clientId + "?" + Utils.TENANT_IDENTIFIER + "&command=assignStaff"; + final String clientId, final String staffId) { + final String CLIENT_ASSIGN_STAFF_URL = "/mifosng-provider/api/v1/clients/" + clientId + "?" + Utils.TENANT_IDENTIFIER + + "&command=assignStaff"; System.out.println("---------------------------------CREATING A CLIENT---------------------------------------------"); - return Utils.performServerPost(requestSpec, responseSpec, CLIENT_ASSIGN_STAFF_URL, assignStaffToClientAsJson(staffId), - "changes"); + return Utils.performServerPost(requestSpec, responseSpec, CLIENT_ASSIGN_STAFF_URL, assignStaffToClientAsJson(staffId), "changes"); } - public static Integer getClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, - final String clientId){ - final String GET_CLIENT_URL = "/mifosng-provider/api/v1/clients/" + clientId + "?" + Utils.TENANT_IDENTIFIER ; - - System.out.println("---------------------------------GET A CLIENT---------------------------------------------"); - return Utils.performServerGet(requestSpec, responseSpec, GET_CLIENT_URL,"staffId"); - + public static Integer getClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String clientId) { + return (Integer) getClient(requestSpec, responseSpec, clientId, "staffId"); } public static String getTestClientAsJSON(final String dateOfJoining, final String officeId) { @@ -65,7 +80,7 @@ public class ClientHelper { return new Gson().toJson(map); } - public static String assignStaffToClientAsJson(final String staffId){ + public static String assignStaffToClientAsJson(final String staffId) { final HashMap map = new HashMap<>(); map.put("staffId", staffId); System.out.println("map : " + map); @@ -80,7 +95,110 @@ public class ClientHelper { assertEquals("ERROR IN CREATING THE CLIENT", generatedClientID, responseClientID); } + public static Object getClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String clientId, + final String jsonReturn) { + final String GET_CLIENT_URL = "/mifosng-provider/api/v1/clients/" + clientId + "?" + Utils.TENANT_IDENTIFIER; + + System.out.println("---------------------------------GET A CLIENT---------------------------------------------"); + return Utils.performServerGet(requestSpec, responseSpec, GET_CLIENT_URL, jsonReturn); + + } + + public static HashMap getClientStatus(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String clientId) { + return (HashMap) getClient(requestSpec, responseSpec, clientId, "status"); + } + private static String randomIDGenerator(final String prefix, final int lenOfRandomSuffix) { return Utils.randomStringGenerator(prefix, lenOfRandomSuffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } + + private String getCloseClientAsJSON() { + final HashMap map = new HashMap<>(); + map.put("locale", CommonConstants.locale); + map.put("dateFormat", CommonConstants.dateFormat); + map.put("closureDate", CREATED_DATE_PLUS_ONE); + map.put("closureReasonId", "12"); + String clientJson = new Gson().toJson(map); + System.out.println(clientJson); + return clientJson; + + } + private String getReactivateClientAsJSON() { + final HashMap 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 getRejectClientAsJSON() { + final HashMap map = new HashMap<>(); + map.put("locale", CommonConstants.locale); + map.put("dateFormat", CommonConstants.dateFormat); + map.put("rejectDate", CREATED_DATE_PLUS_ONE); + map.put("rejectReasonId", "15"); + String clientJson = new Gson().toJson(map); + System.out.println(clientJson); + return clientJson; + + } + private String getActivateClientAsJSON() { + final HashMap 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 map = new HashMap<>(); + map.put("locale", CommonConstants.locale); + map.put("dateFormat", CommonConstants.dateFormat); + map.put("withdrawDate", CREATED_DATE_PLUS_ONE); + map.put("withdrawReasonId", "17"); + String clientJson = new Gson().toJson(map); + System.out.println(clientJson); + return clientJson; + + } + public HashMap closeClient(final Integer clientId) { + System.out.println("--------------------------------- CLOSE CLIENT -------------------------------"); + return performClientActions(createClientOperationURL(CLOSE_CLIENT_COMMAND, clientId), getCloseClientAsJSON(), clientId); + } + + public HashMap reactivateClient(final Integer clientId) { + System.out.println("--------------------------------- REACTIVATE CLIENT -------------------------------"); + return performClientActions(createClientOperationURL(REACTIVATE_CLIENT_COMMAND, clientId), getReactivateClientAsJSON(), clientId); + } + public HashMap rejectClient(final Integer clientId) { + System.out.println("--------------------------------- REJECT CLIENT -------------------------------"); + return performClientActions(createClientOperationURL(REJECT_CLIENT_COMMAND, clientId), getRejectClientAsJSON(), clientId); + } + + public HashMap activateClient(final Integer clientId) { + System.out.println("--------------------------------- ACTIVATE CLIENT -------------------------------"); + return performClientActions(createClientOperationURL(ACTIVATE_CLIENT_COMMAND, clientId), getActivateClientAsJSON(), clientId); + } + public HashMap withdrawClient(final Integer clientId) { + System.out.println("--------------------------------- WITHDRAWN CLIENT -------------------------------"); + 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 HashMap performClientActions(final String postURLForClient, final String jsonToBeSent, final Integer clientId) { + HashMap status = null; + Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForClient, jsonToBeSent, CommonConstants.RESPONSE_STATUS); + HashMap response = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); + + return response; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/CommonConstants.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/CommonConstants.java index 8e29d4792..dbebbd405 100755 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/CommonConstants.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/CommonConstants.java @@ -12,6 +12,7 @@ public interface CommonConstants { public static final String dateFormat = "dd MMMM yyyy"; public static final String RESPONSE_RESOURCE_ID = "resourceId"; public static final String RESPONSE_CHANGES = "changes"; + public static final String RESPONSE_STATUS = "status"; public static final String RESPONSE_ERROR = "errors"; public static final String RESPONSE_ERROR_MESSAGE_CODE = "userMessageGlobalisationCode"; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java index 6c2f3aa4b..441ea97c2 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java @@ -856,6 +856,12 @@ public class CommandWrapper { public boolean isWithdrawal() { return this.actionName.equalsIgnoreCase("WITHDRAWAL"); } + public boolean isWithdrawn() { + return this.actionName.equalsIgnoreCase("WITHDRAW"); + } + public boolean isReactivated() { + return this.actionName.equalsIgnoreCase("REACTIVATE"); + } public boolean isActivation() { return this.actionName.equalsIgnoreCase("ACTIVATE"); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java index a9c83213b..a745e4ae5 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -418,7 +418,32 @@ public class CommandWrapperBuilder { this.href = "/clients/" + clientId + "?command=close&template=true"; return this; } - + + public CommandWrapperBuilder rejectClient(final Long clientId) { + this.actionName = "REJECT"; + this.entityName = "CLIENT"; + this.entityId = clientId; + this.clientId = clientId; + this.href = "/clients/" + clientId + "?command=reject&template=true"; + return this; + } + + public CommandWrapperBuilder withdrawClient(final Long clientId) { + this.actionName = "WITHDRAW"; + this.entityName = "CLIENT"; + this.entityId = clientId; + this.clientId = clientId; + this.href = "/clients/" + clientId + "?command=withdraw&template=true"; + return this; + } + public CommandWrapperBuilder reActivateClient(final Long clientId) { + this.actionName = "REACTIVATE"; + this.entityName = "CLIENT"; + this.entityId = clientId; + this.clientId = clientId; + this.href = "/clients/" + clientId + "?command=reactivate&template=true"; + return this; + } public CommandWrapperBuilder proposeClientTransfer(final Long clientId) { this.actionName = "PROPOSETRANSFER"; this.entityName = "CLIENT"; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java index bb146845e..0387d4713 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java @@ -205,7 +205,13 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer handler = this.applicationContext.getBean("rejectClientTransferCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isUpdateClientSavingsAccount()) { handler = this.applicationContext.getBean("updateClientSavingsAccountCommandHandler", NewCommandSourceHandler.class); - } else { + } else if(wrapper.isReject()){ + handler = this.applicationContext.getBean("rejectClientCommandHandler", NewCommandSourceHandler.class); + }else if(wrapper.isWithdrawn()){ + handler = this.applicationContext.getBean("withdrawClientCommandHandler", NewCommandSourceHandler.class); + }else if(wrapper.isReactivated()){ + handler = this.applicationContext.getBean("reActivateClientCommandHandler", NewCommandSourceHandler.class); + }else { throw new UnsupportedCommandException(wrapper.commandName()); } // end of client diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java index 0ec00bcaf..a1fe1c22b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java @@ -15,6 +15,11 @@ public class ClientApiConstants { public static final String CLIENT_RESOURCE_NAME = "client"; public static final String CLIENT_CLOSURE_REASON = "ClientClosureReason"; + public static final String CLIENT_ACTION_REASON = "ClientActionReason"; + public static final String CLIENT_REJECT_REASON = "ClientRejectReason"; + public static final String CLIENT_WITHDRAW_REASON = "ClientWithdrawReason"; + + public static final String GENDER = "Gender"; public static final String CLIENT_TYPE = "ClientType"; public static final String CLIENT_CLASSIFICATION = "ClientClassification"; @@ -36,9 +41,16 @@ public class ClientApiConstants { public static final String transferOfficeIdParamName = "transferOfficeIdParamName"; public static final String activeParamName = "active"; public static final String activationDateParamName = "activationDate"; + public static final String reactivationDateParamName = "reactivationDate"; public static final String staffIdParamName = "staffId"; public static final String closureDateParamName = "closureDate"; public static final String closureReasonIdParamName = "closureReasonId"; + + public static final String rejectDateParamName = "rejectDate"; + public static final String rejectReasonIdParamName ="rejectReasonId"; + public static final String withdrawDateParamName = "withdrawDate"; + public static final String withdrawReasonIdParamName ="withdrawReasonId"; + public static final String submittedOnDateParamName = "submittedOnDate"; public static final String savingsProductIdParamName = "savingsProductId"; public static final String savingsAccountIdParamName = "savingsAccountId"; @@ -97,7 +109,14 @@ public class ClientApiConstants { public static final Set ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, dateFormatParamName, activationDateParamName)); + public static final Set REACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, + dateFormatParamName, reactivationDateParamName)); public static final Set CLIENT_CLOSE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, dateFormatParamName, closureDateParamName, closureReasonIdParamName)); + + public static final Set CLIENT_REJECT_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,dateFormatParamName,rejectDateParamName,rejectReasonIdParamName)); + + public static final Set CLIENT_WITHDRAW_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,dateFormatParamName,withdrawDateParamName,withdrawReasonIdParamName)); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java index b91043b54..e1f4c2319 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java @@ -91,10 +91,15 @@ public class ClientsApiResource { ClientData clientData = null; this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME); if (is(commandParam, "close")) { - clientData = this.clientReadPlatformService.retrieveAllClosureReasons(ClientApiConstants.CLIENT_CLOSURE_REASON); + clientData = this.clientReadPlatformService.retrieveAllNarrations(ClientApiConstants.CLIENT_CLOSURE_REASON); } else if (is(commandParam, "acceptTransfer")) { - clientData = this.clientReadPlatformService.retrieveAllClosureReasons(ClientApiConstants.CLIENT_CLOSURE_REASON); - } else { + clientData = this.clientReadPlatformService.retrieveAllNarrations(ClientApiConstants.CLIENT_CLOSURE_REASON); + }else if (is(commandParam, "reject")) { + clientData = this.clientReadPlatformService.retrieveAllNarrations(ClientApiConstants.CLIENT_REJECT_REASON); + }else if (is(commandParam, "withdraw")) { + clientData = this.clientReadPlatformService.retrieveAllNarrations(ClientApiConstants.CLIENT_WITHDRAW_REASON); + } + else { clientData = this.clientReadPlatformService.retrieveTemplate(officeId, staffInSelectedOfficeOnly); } @@ -238,11 +243,21 @@ public class ClientsApiResource { } else if (is(commandParam, "updateSavingsAccount")) { commandRequest = builder.updateClientSavingsAccount(clientId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); - } + }else if (is(commandParam,"reject")){ + commandRequest = builder.rejectClient(clientId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + }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); + } + if (result == null) { throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "unassignStaff", "assignStaff", "close", "proposeTransfer", "withdrawTransfer", "acceptTransfer", "rejectTransfer", - "updateSavingsAccount" }); } + "updateSavingsAccount","reject" ,"withdraw","reactivate"}); } return this.toApiJsonSerializer.serialize(result); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java index f85385585..cd706fc6b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java @@ -69,7 +69,7 @@ final public class ClientData implements Comparable { // template private final Collection officeOptions; private final Collection staffOptions; - private final Collection closureReasons; + private final Collection narrations; private final Collection savingProductOptions; private final Collection savingAccountOptions; private final Collection genderOptions; @@ -77,7 +77,7 @@ final public class ClientData implements Comparable { private final Collection clientClassificationOptions; public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection officeOptions, - final Collection staffOptions, final Collection closureReasons, + final Collection staffOptions, final Collection narrations, final Collection genderOptions, final Collection savingProductOptions, final Collection clientTypeOptions, final Collection clientClassificationOptions) { final String accountNo = null; @@ -109,7 +109,7 @@ final public class ClientData implements Comparable { final CodeValueData clientClassification = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, joinedDate, imageId, staffId, - staffName, officeOptions, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, + staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions); @@ -121,11 +121,10 @@ final public class ClientData implements Comparable { clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo, clientData.dateOfBirth, clientData.gender, clientData.activationDate, clientData.imageId, clientData.staffId, - clientData.staffName, templateData.officeOptions, clientData.groups, templateData.staffOptions, - templateData.closureReasons, templateData.genderOptions, clientData.timeline, templateData.savingProductOptions, - clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions, - clientData.clientType, clientData.clientClassification, templateData.clientTypeOptions, - templateData.clientClassificationOptions); + clientData.staffName, templateData.officeOptions, clientData.groups, templateData.staffOptions, templateData.narrations, + templateData.genderOptions, clientData.timeline, templateData.savingProductOptions, clientData.savingsProductId, + clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions, clientData.clientType, + clientData.clientClassification, templateData.clientTypeOptions, templateData.clientClassificationOptions); } @@ -136,7 +135,7 @@ final public class ClientData implements Comparable { clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo, clientData.dateOfBirth, clientData.gender, clientData.activationDate, clientData.imageId, clientData.staffId, - clientData.staffName, clientData.officeOptions, clientData.groups, clientData.staffOptions, clientData.closureReasons, + clientData.staffName, clientData.officeOptions, clientData.groups, clientData.staffOptions, clientData.narrations, clientData.genderOptions, clientData.timeline, clientData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, savingAccountOptions, clientData.clientType, clientData.clientClassification, clientData.clientTypeOptions, clientData.clientClassificationOptions); @@ -262,7 +261,7 @@ final public class ClientData implements Comparable { final String externalId, final String mobileNo, final LocalDate dateOfBirth, final CodeValueData gender, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName, final Collection allowedOffices, final Collection groups, - final Collection staffOptions, final Collection closureReasons, + final Collection staffOptions, final Collection narrations, final Collection genderOptions, final ClientTimelineData timeline, final Collection savingProductOptions, final Long savingsProductId, final String savingsProductName, final Long savingsAccountId, final Collection savingAccountOptions, final CodeValueData clientType, @@ -308,7 +307,8 @@ final public class ClientData implements Comparable { // template this.officeOptions = allowedOffices; this.staffOptions = staffOptions; - this.closureReasons = closureReasons; + this.narrations = narrations; + this.genderOptions = genderOptions; this.clientClassificationOptions = clientClassificationOptions; this.clientTypeOptions = clientTypeOptions; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java index 3c8f65ad4..cd2801c1f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java @@ -345,7 +345,6 @@ public final class ClientDataValidator { .longGreaterThanZero(); } - if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.dateOfBirthParamName, element)) { atLeastOneParameterPassedForUpdate = true; final LocalDate dateOfBirth = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.dateOfBirthParamName, element); @@ -386,8 +385,6 @@ public final class ClientDataValidator { baseDataValidator.reset().anyOfNotNull(forceError); } - - throwExceptionIfValidationWarningsExist(dataValidationErrors); } @@ -515,4 +512,78 @@ public final class ClientDataValidator { } + public void validateRejection(final JsonCommand command) { + + final String json = command.json(); + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_REJECT_DATA_PARAMETERS); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); + + final JsonElement element = command.parsedJson(); + + final LocalDate rejectDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.rejectDateParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.rejectDateParamName).value(rejectDate).notNull(); + + final Long rejectReasonId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.rejectReasonIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.rejectReasonIdParamName).value(rejectReasonId).notNull() + .longGreaterThanZero(); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + + } + + public void validateWithdrawn(final JsonCommand command) { + + final String json = command.json(); + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_WITHDRAW_DATA_PARAMETERS); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); + + final JsonElement element = command.parsedJson(); + + final LocalDate withdrawDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.withdrawDateParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.withdrawDateParamName).value(withdrawDate).notNull(); + + final Long withdrawReasonId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.withdrawReasonIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.withdrawReasonIdParamName).value(withdrawReasonId).notNull() + .longGreaterThanZero(); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + + } + + public void validateReactivate(final JsonCommand command) { + + final String json = command.json(); + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.REACTIVATION_REQUEST_DATA_PARAMETERS); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); + + final JsonElement element = command.parsedJson(); + + final LocalDate reactivationDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.reactivationDateParamName, + element); + baseDataValidator.reset().parameter(ClientApiConstants.reactivationDateParamName).value(reactivationDate).notNull(); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java index 0dd779fa2..98ffb7802 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java @@ -133,9 +133,42 @@ public final class Client extends AbstractPersistable { @Temporal(TemporalType.DATE) private Date closureDate; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reject_reason_cv_id", nullable = true) + private CodeValue rejectReason; + + @Column(name = "rejectedon_date", nullable = true) + @Temporal(TemporalType.DATE) + private Date rejectDate; + + @ManyToOne(optional = true) + @JoinColumn(name = "rejectedon_userid", nullable = true) + private AppUser rejectedBy; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "withdraw_reason_cv_id", nullable = true) + private CodeValue withdrawReason; + + @Column(name = "withdrawn_on_date", nullable = true) + @Temporal(TemporalType.DATE) + private Date withdrawDate; + + @ManyToOne(optional = true) + @JoinColumn(name = "withdraw_on_userid", nullable = true) + private AppUser withdrawnBy; + + @Column(name = "reactivated_on_date", nullable = true) + @Temporal(TemporalType.DATE) + private Date reactivateDate; + + @ManyToOne(optional = true) + @JoinColumn(name = "reactivated_on_userid", nullable = true) + private AppUser reactivatedBy; + + @ManyToOne(optional = true) @JoinColumn(name = "closedon_userid", nullable = true) - private AppUser closeddBy; + private AppUser closedBy; @Column(name = "submittedon_date", nullable = true) @Temporal(TemporalType.DATE) @@ -145,6 +178,14 @@ public final class Client extends AbstractPersistable { @JoinColumn(name = "submittedon_userid", nullable = true) private AppUser submittedBy; + @Column(name = "updated_on", nullable = true) + @Temporal(TemporalType.DATE) + private Date updatedOnDate; + + @ManyToOne(optional = true) + @JoinColumn(name = "updated_by", nullable = true) + private AppUser updatedBy; + @ManyToOne(optional = true) @JoinColumn(name = "activatedon_userid", nullable = true) private AppUser activatedBy; @@ -693,7 +734,7 @@ public final class Client extends AbstractPersistable { public void close(final AppUser currentUser, final CodeValue closureReason, final Date closureDate) { this.closureReason = closureReason; this.closureDate = closureDate; - this.closeddBy = currentUser; + this.closedBy = currentUser; this.status = ClientStatus.CLOSED.getValue(); } @@ -805,4 +846,32 @@ public final class Client extends AbstractPersistable { } return dateOfBirth; } + + public void reject(AppUser currentUser, CodeValue rejectReason, Date rejectDate) { + this.rejectReason = rejectReason; + this.rejectDate = rejectDate; + this.rejectedBy = currentUser; + this.updatedBy = currentUser; + this.updatedOnDate = rejectDate; + this.status = ClientStatus.REJECTED.getValue(); + + } + + public void withdraw(AppUser currentUser, CodeValue withdrawReason, Date withdrawDate) { + this.withdrawReason = withdrawReason; + this.withdrawDate = withdrawDate; + this.withdrawnBy = currentUser; + this.updatedBy = currentUser; + this.updatedOnDate = withdrawDate; + this.status = ClientStatus.WITHDRAWN.getValue(); + + } + public void reActivate(AppUser currentUser, Date reactivateDate) { + this.reactivateDate = reactivateDate; + this.reactivatedBy = currentUser; + this.updatedBy = currentUser; + this.updatedOnDate = reactivateDate; + this.status = ClientStatus.PENDING.getValue(); + + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java index bbffdfcfa..86b4866c7 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java @@ -29,6 +29,12 @@ public class ClientEnumerations { case CLOSED: optionData = new EnumOptionData(ClientStatus.CLOSED.getValue().longValue(), ClientStatus.CLOSED.getCode(), "Closed"); break; + case REJECTED: + optionData = new EnumOptionData(ClientStatus.REJECTED.getValue().longValue(), ClientStatus.REJECTED.getCode(), "Rejected"); + break; + case WITHDRAWN: + optionData = new EnumOptionData(ClientStatus.WITHDRAWN.getValue().longValue(), ClientStatus.WITHDRAWN.getCode(), "Withdrawn"); + break; case TRANSFER_IN_PROGRESS: optionData = new EnumOptionData(ClientStatus.TRANSFER_IN_PROGRESS.getValue().longValue(), ClientStatus.TRANSFER_IN_PROGRESS.getCode(), "Transfer in progress"); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientStatus.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientStatus.java index 405b48f7e..7fcf8b1cb 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientStatus.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientStatus.java @@ -15,7 +15,10 @@ public enum ClientStatus { ACTIVE(300, "clientStatusType.active"), // TRANSFER_IN_PROGRESS(303, "clientStatusType.transfer.in.progress"), // TRANSFER_ON_HOLD(304, "clientStatusType.transfer.on.hold"), // - CLOSED(600, "clientStatusType.closed"); + CLOSED(600, "clientStatusType.closed"), + REJECTED(700,"clientStatusType.rejected"), + WITHDRAWN(800,"clientStatusType.withdraw"); + private final Integer value; private final String code; @@ -39,6 +42,13 @@ public enum ClientStatus { case 600: enumeration = ClientStatus.CLOSED; break; + case 700: + enumeration = ClientStatus.REJECTED; + break; + case 800: + enumeration = ClientStatus.WITHDRAWN; + break; + } return enumeration; } @@ -67,11 +77,16 @@ public enum ClientStatus { public boolean isActive() { return this.value.equals(ClientStatus.ACTIVE.getValue()); } - + public boolean isClosed() { return this.value.equals(ClientStatus.CLOSED.getValue()); } - + public boolean isRejected(){ + return this.value.equals(ClientStatus.REJECTED.getValue()); + } + public boolean isWithdrawn(){ + return this.value.equals(ClientStatus.WITHDRAWN.getValue()); + } public boolean isTransferInProgress() { return this.value.equals(ClientStatus.TRANSFER_IN_PROGRESS.getValue()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/ReActivateClientCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/ReActivateClientCommandHandler.java new file mode 100644 index 000000000..8c5077e46 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/ReActivateClientCommandHandler.java @@ -0,0 +1,33 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.handler; + +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ReActivateClientCommandHandler implements NewCommandSourceHandler { + + private final ClientWritePlatformService clientWritePlatformService; + + @Autowired + public ReActivateClientCommandHandler(final ClientWritePlatformService clientWritePlatformService) { + this.clientWritePlatformService = clientWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.clientWritePlatformService.reActivateClient(command.entityId(), command); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/RejectClientCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/RejectClientCommandHandler.java new file mode 100644 index 000000000..8a0fd3e1f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/RejectClientCommandHandler.java @@ -0,0 +1,33 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.handler; +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Service +public class RejectClientCommandHandler implements NewCommandSourceHandler { + + private final ClientWritePlatformService clientWritePlatformService; + + @Autowired + public RejectClientCommandHandler(final ClientWritePlatformService clientWritePlatformService) { + this.clientWritePlatformService = clientWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.clientWritePlatformService.rejectClient(command.entityId(), command); + } + +} + + diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/WithdrawClientCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/WithdrawClientCommandHandler.java new file mode 100644 index 000000000..b60e0702c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/handler/WithdrawClientCommandHandler.java @@ -0,0 +1,34 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.handler; + +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +public class WithdrawClientCommandHandler implements NewCommandSourceHandler { + + private final ClientWritePlatformService clientWritePlatformService; + +@Autowired +public WithdrawClientCommandHandler(final ClientWritePlatformService clientWritePlatformService) { + this.clientWritePlatformService = clientWritePlatformService; +} + +@Transactional +@Override +public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.clientWritePlatformService.withdrawClient(command.entityId(), command); +} + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformService.java index da9286677..f945cd792 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformService.java @@ -31,5 +31,5 @@ public interface ClientReadPlatformService { Collection retrieveActiveClientMembersOfCenter(final Long centerId); - ClientData retrieveAllClosureReasons(String clientClosureReason); + ClientData retrieveAllNarrations(String clientNarrations); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java index 52fc8315c..e1853a345 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java @@ -661,12 +661,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService } @Override - public ClientData retrieveAllClosureReasons(final String clientClosureReason) { - final List closureReasons = new ArrayList<>( - this.codeValueReadPlatformService.retrieveCodeValuesByCode(clientClosureReason)); + public ClientData retrieveAllNarrations(final String clientNarrations) { + final List narrations = new ArrayList<>( + this.codeValueReadPlatformService.retrieveCodeValuesByCode(clientNarrations)); final Collection clientTypeOptions = null; final Collection clientClassificationOptions = null; - return ClientData.template(null, null, null, null, closureReasons, null, null, clientTypeOptions, clientClassificationOptions); + return ClientData.template(null, null, null, null, narrations, null, null, clientTypeOptions, clientClassificationOptions); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformService.java index f69973812..a5793d957 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformService.java @@ -26,4 +26,10 @@ public interface ClientWritePlatformService { CommandProcessingResult updateDefaultSavingsAccount(Long clientId, JsonCommand command); + CommandProcessingResult rejectClient(Long entityId, JsonCommand command); + + CommandProcessingResult withdrawClient(Long entityId, JsonCommand command); + + CommandProcessingResult reActivateClient(Long entityId, JsonCommand command); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index cfe532718..80bebfec1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -575,7 +575,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP } /* - * To become a part of a group, group may have set of criteria to be met + * To become a part of a group, group may have set of criteria to be m et * before client can become member of it. */ private void validateParentGroupRulesBeforeClientActivation(Client client) { @@ -593,4 +593,89 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP } } } -} \ No newline at end of file + + @Override + public CommandProcessingResult rejectClient(final Long entityId, final JsonCommand command) { + final AppUser currentUser = this.context.authenticatedUser(); + this.fromApiJsonDeserializer.validateRejection(command); + + final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId); + final LocalDate rejectDate = command.localDateValueOfParameterNamed(ClientApiConstants.rejectDateParamName); + final Long rejectReasonId = command.longValueOfParameterNamed(ClientApiConstants.rejectReasonIdParamName); + + final CodeValue rejectReason = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection( + ClientApiConstants.CLIENT_REJECT_REASON, rejectReasonId); + + if (ClientStatus.fromInt(client.getStatus()).isRejected()) { + final String errorMessage = "Client is already rejected."; + throw new InvalidClientStateTransitionException("rejected", "is.already.rejected", errorMessage); + } else if (client.isNotPending() || client.getSubmittedOnDate().isAfter(rejectDate)) { + final String errorMessage = "The client is active or The client rejetDate cannot be before the client SubmittedDate."; + throw new InvalidClientStateTransitionException("rejected", "date.cannot.before.client.submitted.date", errorMessage, + rejectDate, client.getSubmittedOnDate()); + } else { + client.reject(currentUser, rejectReason, rejectDate.toDate()); + this.clientRepository.saveAndFlush(client); + } + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withClientId(entityId) // + .withEntityId(entityId) // + .build(); + } + + @Override + public CommandProcessingResult withdrawClient(Long entityId, JsonCommand command) { + final AppUser currentUser = this.context.authenticatedUser(); + this.fromApiJsonDeserializer.validateWithdrawn(command); + + final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId); + final LocalDate withdrawDate = command.localDateValueOfParameterNamed(ClientApiConstants.withdrawDateParamName); + final Long withdrawReasonId = command.longValueOfParameterNamed(ClientApiConstants.withdrawReasonIdParamName); + + final CodeValue withdrawReason = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection( + ClientApiConstants.CLIENT_WITHDRAW_REASON, withdrawReasonId); + + if (ClientStatus.fromInt(client.getStatus()).isRejected()) { + final String errorMessage = "Client is already Withdrawn."; + throw new InvalidClientStateTransitionException("withdrawn", "is.already.withdrawn", errorMessage); + } else if (client.isNotPending() || client.getSubmittedOnDate().isAfter(withdrawDate)) { + final String errorMessage = "The client is active or The client withdrawDate cannot be before the client SubmittedDate."; + throw new InvalidClientStateTransitionException("withdrawn", "date.cannot.before.client.submitted.date", errorMessage, + withdrawDate, client.getSubmittedOnDate()); + } else { + client.withdraw(currentUser, withdrawReason, withdrawDate.toDate()); + this.clientRepository.saveAndFlush(client); + } + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withClientId(entityId) // + .withEntityId(entityId) // + .build(); + } + + @Override + public CommandProcessingResult reActivateClient(Long entityId, JsonCommand command) { + final AppUser currentUser = this.context.authenticatedUser(); + this.fromApiJsonDeserializer.validateReactivate(command); + + final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId); + final LocalDate reactivateDate = command.localDateValueOfParameterNamed(ClientApiConstants.reactivationDateParamName); + + + if (ClientStatus.fromInt(client.getStatus()).isActive()) { + final String errorMessage = "Client is already activated."; + throw new InvalidClientStateTransitionException("activated", "is.already.activated", errorMessage); + } else if (client.isClosed()) { + client.reActivate(currentUser, reactivateDate.toDate()); + this.clientRepository.saveAndFlush(client); + } + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withClientId(entityId) // + .withEntityId(entityId) // + .build(); + } +} diff --git a/mifosng-provider/src/main/resources/sql/migrations/core_db/V220__Client_Lifecycle_Adding_Statuses.sql b/mifosng-provider/src/main/resources/sql/migrations/core_db/V220__Client_Lifecycle_Adding_Statuses.sql new file mode 100644 index 000000000..c0b838ac0 --- /dev/null +++ b/mifosng-provider/src/main/resources/sql/migrations/core_db/V220__Client_Lifecycle_Adding_Statuses.sql @@ -0,0 +1,52 @@ + + + +ALTER TABLE `m_client` + ADD COLUMN `reject_reason_cv_id` INT(11) NULL DEFAULT NULL AFTER `client_classification_cv_id`, + ADD COLUMN `rejectedon_date` DATE NULL DEFAULT NULL AFTER `reject_reason_cv_id`, + ADD COLUMN `rejectedon_userid` BIGINT(20) NULL DEFAULT NULL AFTER `rejectedon_date`, + ADD COLUMN `withdraw_reason_cv_id` INT(11) NULL DEFAULT NULL AFTER `rejectedon_userid`, + ADD COLUMN `withdrawn_on_date` DATE NULL DEFAULT NULL AFTER `withdraw_reason_cv_id`, + ADD COLUMN `withdraw_on_userid` BIGINT(20) NULL DEFAULT NULL AFTER `withdrawn_on_date`, + ADD CONSTRAINT `FK_m_client_type_mcode_value_reject` FOREIGN KEY (`reject_reason_cv_id`) REFERENCES `m_code_value` (`id`), + ADD CONSTRAINT `FK_m_client_type_m_code_value_withdraw` FOREIGN KEY (`withdraw_reason_cv_id`) REFERENCES `m_code_value` (`id`); +SELECT `DEFAULT_COLLATION_NAME` FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME`='mifostenant-default'; +SHOW TABLE STATUS FROM `mifostenant-default`; +SHOW FUNCTION STATUS WHERE `Db`='mifostenant-default'; +SHOW PROCEDURE STATUS WHERE `Db`='mifostenant-default'; +SHOW TRIGGERS FROM `mifostenant-default`; +SHOW EVENTS FROM `mifostenant-default`; +SHOW CREATE TABLE `mifostenant-default`.`m_client`; +/* Entering session "mifosx" */ + +ALTER TABLE `m_client` + ADD COLUMN `updated_by` BIGINT(20) NULL DEFAULT NULL AFTER `closedon_date`, + ADD COLUMN `updated_on` DATE NULL DEFAULT NULL AFTER `updated_by`; + + + +INSERT INTO `m_permission` ( `grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ( 'portfolio', 'REJECT_CLIENT', 'CLIENT', 'REJECT', 1); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ( 'portfolio', 'REJECT_CLIENT_CHECKER', 'CLIENT', 'REJECT_CHECKER', 0); + +INSERT INTO `m_permission` ( `grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ( 'portfolio', 'WITHDRAW_CLIENT', 'CLIENT', 'WITHDRAW', 1); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'WITHDRAW_CLIENT_CHECKER', 'CLIENT', 'WITHDRAW_CHECKER', 0); + + +INSERT INTO `m_code` ( `code_name`, `is_system_defined`) VALUES ( 'ClientRejectReason', 1); + + +INSERT INTO `m_code_value` ( `code_id`, `code_value`, `order_position`, `code_score`) VALUES ( (SELECT id from m_code where code_name = 'ClientRejectReason') , 'Client Rejected', 1, NULL); + +INSERT INTO `m_code` ( `code_name`, `is_system_defined`) VALUES ( 'ClientWithdrawReason', 1); + +INSERT INTO `m_code_value` ( `code_id`, `code_value`, `order_position`, `code_score`) VALUES ( (SELECT id from m_code where code_name = 'ClientWithdrawReason') , 'Client Withdrawn', 1, NULL); + + + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ( 'portfolio', 'REACTIVATE_CLIENT', 'CLIENT', 'REACTIVATE', 1); +INSERT INTO `m_permission` ( `grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ( 'portfolio', 'REACTIVATE_CLIENT_CHECKER', 'CLIENT', 'REACTIVATE_CHECKER', 0); + + +ALTER TABLE `m_client` + ADD COLUMN `reactivated_on_date` DATE NULL AFTER `withdraw_on_userid`, + ADD COLUMN `reactivated_on_userid` BIGINT(20) NULL AFTER `reactivated_on_date`; \ No newline at end of file