close client functionality
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('ClientClosureReason', 1)
|
||||
|
||||
ALTER TABLE `m_client` ADD COLUMN `closure_reason_cv_id` INT(11) NULL DEFAULT NULL,
|
||||
ADD COLUMN `closedon_date` DATE NULL DEFAULT NULL,
|
||||
ADD CONSTRAINT `FK_m_client_m_code` FOREIGN KEY (`closure_reason_cv_id`) REFERENCES `m_code_value` (`id`)
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`) VALUES ('portfolio', 'CLOSE_CLIENT', 'CLIENT', 'CLOSE')
|
||||
|
||||
@@ -553,4 +553,7 @@ public class CommandWrapper {
|
||||
return this.actionName.equalsIgnoreCase("ASSIGNSTAFF") && this.entityName.equalsIgnoreCase("CLIENT");
|
||||
}
|
||||
|
||||
public boolean isClientClose() {
|
||||
return this.actionName.equalsIgnoreCase("CLOSE") && this.entityName.equalsIgnoreCase("CLIENT");
|
||||
}
|
||||
}
|
||||
+9
@@ -336,6 +336,15 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/clients/" + clientId + "?command=activate&template=true";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder closeClient(final Long clientId) {
|
||||
this.actionName = "CLOSE";
|
||||
this.entityName = "CLIENT";
|
||||
this.entityId = clientId;
|
||||
this.clientId = clientId;
|
||||
this.href = "/clients/" + clientId + "?command=close&template=true";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateClient(final Long clientId) {
|
||||
this.actionName = "UPDATE";
|
||||
|
||||
+2
@@ -161,6 +161,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
handler = this.applicationContext.getBean("unassignClientStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isClientAssignStaff()) {
|
||||
handler = this.applicationContext.getBean("assignClientStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isClientClose()) {
|
||||
handler = this.applicationContext.getBean("closeClientCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
+6
-1
@@ -14,6 +14,7 @@ import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
public class ClientApiConstants {
|
||||
|
||||
public static final String CLIENT_RESOURCE_NAME = "client";
|
||||
public static final String CLIENT_CLOSURE_REASON = "ClientClosureReason";
|
||||
|
||||
// general
|
||||
public static final String localeParamName = "locale";
|
||||
@@ -32,7 +33,8 @@ public class ClientApiConstants {
|
||||
public static final String activeParamName = "active";
|
||||
public static final String activationDateParamName = "activationDate";
|
||||
public static final String staffIdParamName = "staffId";
|
||||
|
||||
public static final String closureDateParamName = "closureDate";
|
||||
public static final String closureReasonIdParamName = "closureReasonId";
|
||||
// response parameters
|
||||
public static final String statusParamName = "status";
|
||||
public static final String hierarchyParamName = "hierarchy";
|
||||
@@ -68,4 +70,7 @@ public class ClientApiConstants {
|
||||
|
||||
public static final Set<String> ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, activationDateParamName));
|
||||
|
||||
public static final Set<String> CLIENT_CLOSE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, closureDateParamName, closureReasonIdParamName));
|
||||
}
|
||||
+16
-5
@@ -84,11 +84,18 @@ public class ClientsApiResource {
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
|
||||
@QueryParam("commandParam") final String commandParam) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
|
||||
final ClientData clientData = this.clientReadPlatformService.retrieveTemplate(officeId);
|
||||
ClientData clientData = null;
|
||||
context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
if (is(commandParam, "close")) {
|
||||
clientData = this.clientReadPlatformService.retrieveAllClosureReasons(ClientApiConstants.CLIENT_CLOSURE_REASON);
|
||||
}else{
|
||||
clientData = this.clientReadPlatformService.retrieveTemplate(officeId);
|
||||
}
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS);
|
||||
@@ -194,17 +201,21 @@ public class ClientsApiResource {
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
|
||||
CommandProcessingResult result = null;
|
||||
CommandWrapper commandRequest = null;
|
||||
if (is(commandParam, "activate")) {
|
||||
final CommandWrapper commandRequest = builder.activateClient(clientId).build();
|
||||
commandRequest = builder.activateClient(clientId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
} else if (is(commandParam, "assignStaff")) {
|
||||
final CommandWrapper commandRequest = builder.assignClientStaff(clientId).build();
|
||||
commandRequest = builder.assignClientStaff(clientId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else if (is(commandParam, "unassignStaff")) {
|
||||
final CommandWrapper commandRequest = builder.unassignClientStaff(clientId).build();
|
||||
commandRequest = builder.unassignClientStaff(clientId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else if(is(commandParam, "close")) {
|
||||
commandRequest = builder.closeClient(clientId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
|
||||
+14
-10
@@ -13,6 +13,7 @@ import org.apache.commons.lang.builder.CompareToBuilder;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
@@ -49,14 +50,15 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
|
||||
// associations
|
||||
private final Collection<GroupGeneralData> groups;
|
||||
|
||||
|
||||
// template
|
||||
private final Collection<OfficeData> officeOptions;
|
||||
private final Collection<StaffData> staffOptions;
|
||||
|
||||
private final Collection<CodeValueData> closureReasons;
|
||||
|
||||
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions,
|
||||
final Collection<StaffData> staffOptions) {
|
||||
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, joinedDate, null, null, null, officeOptions, null, staffOptions);
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> closureReasons) {
|
||||
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, joinedDate, null, null, null, officeOptions, null, staffOptions, closureReasons);
|
||||
}
|
||||
|
||||
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeData> allowedOffices, final Collection<StaffData> staffOptions) {
|
||||
@@ -64,14 +66,14 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
||||
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
||||
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName,
|
||||
allowedOffices, clientData.groups, staffOptions);
|
||||
allowedOffices, clientData.groups, staffOptions, null);
|
||||
}
|
||||
|
||||
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
||||
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
||||
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName,
|
||||
clientData.officeOptions, parentGroups, clientData.staffOptions);
|
||||
clientData.officeOptions, parentGroups, clientData.staffOptions, null);
|
||||
}
|
||||
|
||||
public static ClientData clientIdentifier(final Long id, final String accountNo, final EnumOptionData status, final String firstname,
|
||||
@@ -79,11 +81,11 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
final String officeName) {
|
||||
|
||||
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName, null,
|
||||
null, null, null, null, null, null,null);
|
||||
null, null, null, null, null, null,null, null);
|
||||
}
|
||||
|
||||
public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
|
||||
return new ClientData(null, null, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null, null, null, null);
|
||||
return new ClientData(null, null, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static ClientData instance(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
|
||||
@@ -91,13 +93,14 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
final String displayName, final String externalId, final LocalDate activationDate, final Long imageId, final Long staffId,
|
||||
final String staffName) {
|
||||
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||
externalId, activationDate, imageId, staffId, staffName, null, null, null);
|
||||
externalId, activationDate, imageId, staffId, staffName, null, null, null, null);
|
||||
}
|
||||
|
||||
private ClientData(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName, final Long id,
|
||||
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
|
||||
final String externalId, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
|
||||
final Collection<OfficeData> allowedOffices, final Collection<GroupGeneralData> groups, final Collection<StaffData> staffOptions) {
|
||||
final Collection<OfficeData> allowedOffices, final Collection<GroupGeneralData> groups, final Collection<StaffData> staffOptions,
|
||||
final Collection<CodeValueData> closureReasons) {
|
||||
this.accountNo = accountNo;
|
||||
this.status = status;
|
||||
if (status != null) {
|
||||
@@ -130,6 +133,7 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
// template
|
||||
this.officeOptions = allowedOffices;
|
||||
this.staffOptions = staffOptions;
|
||||
this.closureReasons = closureReasons;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
|
||||
+25
@@ -374,4 +374,29 @@ public final class ClientDataValidator {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
}
|
||||
|
||||
public void validateClose(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.CLIENT_CLOSE_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final LocalDate closureDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.closureDateParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.closureDateParamName).value(closureDate).notNull();
|
||||
|
||||
final Long closureReasonId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.closureReasonIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.closureReasonIdParamName).value(closureReasonId).notNull().longGreaterThanZero();
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -95,6 +95,15 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
|
||||
@Transient
|
||||
private boolean accountNumberRequiresAutoGeneration = false;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "closure_reason_cv_id", nullable = true)
|
||||
private Long closureReasonId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "closedon_date", nullable = true)
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date closureDate;
|
||||
|
||||
public static Client createNew(final Office clientOffice, final Group clientParentGroup, final Staff staff, final JsonCommand command) {
|
||||
|
||||
@@ -447,4 +456,14 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
this.staff = staff;
|
||||
}
|
||||
|
||||
|
||||
public void close(final Long closureReasonId, final Date closureDate) {
|
||||
this.closureReasonId = closureReasonId;
|
||||
this.closureDate = closureDate;
|
||||
this.status = ClientStatus.CLOSED.getValue();
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown an action to transition a loan from one state to another violates a domain rule.
|
||||
*/
|
||||
public class InvalidClientStateTransitionException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public InvalidClientStateTransitionException(final String action, String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
||||
super("error.msg.client." + action + "." + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
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 CloseClientCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final ClientWritePlatformService clientWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public CloseClientCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
|
||||
this.clientWritePlatformService = clientWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.clientWritePlatformService.closeClient(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+2
@@ -33,4 +33,6 @@ public interface ClientReadPlatformService {
|
||||
ClientData retrieveClientByIdentifier(Long identifierTypeId, String identifierKey);
|
||||
|
||||
Collection<ClientData> retrieveClientMembersOfGroup(Long groupId);
|
||||
|
||||
ClientData retrieveAllClosureReasons(String clientClosureReason);
|
||||
}
|
||||
+14
-3
@@ -13,6 +13,8 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
@@ -51,7 +53,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
private final PlatformSecurityContext context;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
// data mappers
|
||||
private final PaginationHelper<ClientData> paginationHelper = new PaginationHelper<ClientData>();
|
||||
private final ClientMapper clientMapper = new ClientMapper();
|
||||
@@ -61,11 +63,13 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
|
||||
@Autowired
|
||||
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService) {
|
||||
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService,
|
||||
final CodeValueReadPlatformService codeValueReadPlatformService) {
|
||||
this.context = context;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.staffReadPlatformService = staffReadPlatformService;
|
||||
this.codeValueReadPlatformService = codeValueReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,7 +86,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
staffOptions = null;
|
||||
}
|
||||
|
||||
return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions);
|
||||
return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -586,4 +590,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
}
|
||||
return defaultOfficeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientData retrieveAllClosureReasons(String clientClosureReason) {
|
||||
final List<CodeValueData> closureReasons = new ArrayList<CodeValueData>(codeValueReadPlatformService.retrieveCodeValuesByCode(clientClosureReason));
|
||||
return ClientData.template(null, null, null, null, closureReasons);
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -19,6 +19,8 @@ public interface ClientWritePlatformService {
|
||||
CommandProcessingResult deleteClient(Long clientId);
|
||||
|
||||
CommandProcessingResult unassignClientStaff(Long clientId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult closeClient(final Long clientId, final JsonCommand command);
|
||||
|
||||
CommandProcessingResult assignClientStaff(Long clientId, JsonCommand command);
|
||||
|
||||
|
||||
+75
-1
@@ -13,6 +13,7 @@ import java.util.Map;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
@@ -29,13 +30,19 @@ import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
|
||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.client.domain.ClientStatus;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientHasNoStaffException;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
|
||||
import org.mifosplatform.portfolio.client.exception.InvalidClientStateTransitionException;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.mifosplatform.portfolio.note.domain.Note;
|
||||
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -56,12 +63,16 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
private final ClientDataValidator fromApiJsonDeserializer;
|
||||
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
||||
private final StaffRepositoryWrapper staffRepository;
|
||||
private final CodeValueRepositoryWrapper codeValueRepository;
|
||||
private final LoanRepository loanRepository;
|
||||
private final SavingsAccountRepository savingsRepository;
|
||||
|
||||
@Autowired
|
||||
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository,
|
||||
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
|
||||
final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository) {
|
||||
final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository, final CodeValueRepositoryWrapper codeValueRepository,
|
||||
final LoanRepository loanRepository, final SavingsAccountRepository savingsRepository) {
|
||||
this.context = context;
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepository = officeRepository;
|
||||
@@ -70,6 +81,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
||||
this.groupRepository = groupRepository;
|
||||
this.staffRepository = staffRepository;
|
||||
this.codeValueRepository = codeValueRepository;
|
||||
this.loanRepository = loanRepository;
|
||||
this.savingsRepository = savingsRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -305,4 +319,64 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.with(actualChanges) //
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult closeClient(final Long clientId, final JsonCommand command) {
|
||||
try {
|
||||
this.fromApiJsonDeserializer.validateClose(command);
|
||||
|
||||
Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(ClientApiConstants.closureDateParamName);
|
||||
final Long closureReasonId = command.longValueOfParameterNamed(ClientApiConstants.closureReasonIdParamName);
|
||||
|
||||
this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_CLOSURE_REASON, closureReasonId);
|
||||
|
||||
if (ClientStatus.fromInt(client.getStatus()).isClosed()) {
|
||||
final String errorMessage = "Client is alread closed.";
|
||||
throw new InvalidClientStateTransitionException("close", "is.already.closed", errorMessage);
|
||||
}
|
||||
|
||||
if (client.isNotPending() && client.getActivationLocalDate().isAfter(closureDate)) {
|
||||
final String errorMessage = "The client closureDate cannot be before the client ActivationDate.";
|
||||
throw new InvalidClientStateTransitionException("close", "date.cannot.before.client.actvation.date", errorMessage,
|
||||
closureDate, client.getActivationLocalDate());
|
||||
}
|
||||
|
||||
List<Loan> clientLoans = this.loanRepository.findLoanByClientId(clientId);
|
||||
|
||||
for (Loan loan : clientLoans) {
|
||||
LoanStatusMapper loanStatus = new LoanStatusMapper(loan.status().getValue());
|
||||
if (loanStatus.isOpen()) {
|
||||
final String errorMessage = "Client cannot be closed because of non-closed loans.";
|
||||
throw new InvalidClientStateTransitionException("close", "loan.non-closed", errorMessage);
|
||||
} else if (loanStatus.isClosed() && loan.getClosedOnDate().after(closureDate.toDate())) {
|
||||
final String errorMessage = "The client closureDate cannot be before the loan closedOnDate.";
|
||||
throw new InvalidClientStateTransitionException("close", "date.cannot.before.loan.closed.date", errorMessage,
|
||||
closureDate, loan.getClosedOnDate());
|
||||
}
|
||||
}
|
||||
List<SavingsAccount> clientSavingAccounts = this.savingsRepository.findSavingAccountByClientId(clientId);
|
||||
|
||||
for (SavingsAccount saving : clientSavingAccounts) {
|
||||
if (saving.isActive()) {
|
||||
final String errorMessage = "Client cannot be closed because of non-closed savings account.";
|
||||
throw new InvalidClientStateTransitionException("close", "non-closed.savings.account", errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
client.close(closureReasonId, closureDate.toDate());
|
||||
this.clientRepository.saveAndFlush(client);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withClientId(clientId) //
|
||||
.withEntityId(clientId) //
|
||||
.build();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
-3
@@ -2317,8 +2317,12 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
this.transactionProcessorFactory = transactionProcessorFactory;
|
||||
}
|
||||
|
||||
public boolean isSyncDisbursementWithMeeting() {
|
||||
return this.syncDisbursementWithMeeting == null ? false : this.syncDisbursementWithMeeting;
|
||||
}
|
||||
public boolean isSyncDisbursementWithMeeting() {
|
||||
return this.syncDisbursementWithMeeting == null ? false : this.syncDisbursementWithMeeting;
|
||||
}
|
||||
|
||||
public Date getClosedOnDate() {
|
||||
return this.closedOnDate;
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -16,4 +16,7 @@ public interface LoanRepository extends JpaRepository<Loan, Long>,
|
||||
JpaSpecificationExecutor<Loan> {
|
||||
@Query("from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId")
|
||||
List<Loan> findByClientIdAndGroupId(@Param("clientId") Long clientId, @Param("groupId") Long groupId);
|
||||
|
||||
@Query("from Loan loan where loan.client.id = :clientId")
|
||||
List<Loan> findLoanByClientId(@Param("clientId") Long clientId);
|
||||
}
|
||||
+6
@@ -5,9 +5,15 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface SavingsAccountRepository extends JpaRepository<SavingsAccount, Long>, JpaSpecificationExecutor<SavingsAccount> {
|
||||
|
||||
@Query("from SavingsAccount s_acc where s_acc.client.id = :clientId")
|
||||
List<SavingsAccount> findSavingAccountByClientId(@Param("clientId") Long clientId);
|
||||
}
|
||||
Reference in New Issue
Block a user