Merge branch 'PR209' into develop

This commit is contained in:
Adi Raju
2016-08-16 16:25:51 +05:30
14 changed files with 865 additions and 54 deletions
@@ -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";
@@ -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,
@@ -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",
@@ -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);
}
}
@@ -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;
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
@@ -844,4 +844,59 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
.withEntityId(entityId) //
.build();
}
}
@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();
}
}
@@ -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);