diff --git a/mifosng-db/patches/21-add_group_permission_code.sql b/mifosng-db/patches/21-add_group_permission_code.sql new file mode 100644 index 000000000..03cddc2e8 --- /dev/null +++ b/mifosng-db/patches/21-add_group_permission_code.sql @@ -0,0 +1,2 @@ +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNASSIGNSTAFF_GROUP', 'GROUP', 'UNASSIGNSTAFF', 1); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNASSIGNSTAFF_GROUP_CHECKER', 'GROUP', 'UNASSIGNSTAFF', 1); 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 d22f72eae..564131fd2 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java @@ -367,6 +367,10 @@ public class CommandWrapper { return isDatatableResource() && isUpdateOperation() && this.apptableId != null && this.datatableId != null; } + public boolean isUnassignStaff() { + return this.actionName.equalsIgnoreCase("UNASSIGNSTAFF") && this.entityName.equalsIgnoreCase("GROUP"); + } + public String commandName() { return this.actionName + "_" + this.entityName; } @@ -461,5 +465,10 @@ public class CommandWrapper { } return isnoteResource; } + + public boolean isGroupResource() { + return this.entityName.equalsIgnoreCase("GROUP"); + } + } \ No newline at end of file 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 8285f166c..c2b1e1ce6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -904,4 +904,35 @@ public class CommandWrapperBuilder { this.href = "/" + resourceType + "/" + resourceId + "/calendars/" + noteId; return this; } + + public CommandWrapperBuilder createGroup() { + this.actionName = "CREATE"; + this.entityName = "GROUP"; + this.href = "/groups/template"; + return this; + } + + public CommandWrapperBuilder updateGroup(final Long groupId) { + this.actionName = "UPDATE"; + this.entityName = "GROUP"; + this.entityId = groupId; + this.href = "/groups/" + groupId; + return this; + } + + public CommandWrapperBuilder unassignStaff(final Long groupId) { + this.actionName = "UNASSIGNSTAFF"; + this.entityName = "GROUP"; + this.entityId = groupId; + this.href = "/groups/" + groupId; + return this; + } + + public CommandWrapperBuilder deleteGroup(final Long groupId) { + this.actionName = "DELETE"; + this.entityName = "GROUP"; + this.entityId = groupId; + this.href = "/groups/" + groupId; + return this; + } } \ No newline at end of file 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 ec951ebfe..a64ee7bcb 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java @@ -415,6 +415,19 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer } else { throw new UnsupportedCommandException(wrapper.commandName()); } + } else if (wrapper.isGroupResource()) { + if (wrapper.isCreate()) { + handler = applicationContext.getBean("createGroupCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isUpdate()) { + handler = applicationContext.getBean("updateGroupCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isUnassignStaff()) { + handler = applicationContext.getBean("unassignStaffCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isDelete()) { + handler = applicationContext.getBean("deleteGroupCommandHandler", NewCommandSourceHandler.class); + } else { + throw new UnsupportedCommandException(wrapper.commandName()); + } + } else { throw new UnsupportedCommandException(wrapper.commandName()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/PortfolioApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/PortfolioApiDataConversionService.java deleted file mode 100644 index f88680c1c..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/PortfolioApiDataConversionService.java +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 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.group; - -import org.mifosplatform.portfolio.group.command.GroupCommand; - -public interface PortfolioApiDataConversionService { - - GroupCommand convertJsonToGroupCommand(Long resourceIdentifier, String json); -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/PortfolioApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/PortfolioApiDataConversionServiceImpl.java deleted file mode 100644 index d47c2c2ba..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/PortfolioApiDataConversionServiceImpl.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * 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.group; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; -import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException; -import org.mifosplatform.portfolio.group.command.GroupCommand; -import org.springframework.stereotype.Service; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.reflect.TypeToken; - -@Service -public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataConversionService { - - /** - * Google-gson class for converting to and from json. - */ - private final Gson gsonConverter; - - public PortfolioApiDataConversionServiceImpl() { - this.gsonConverter = new Gson(); - } - - @Override - public GroupCommand convertJsonToGroupCommand(final Long resourceIdentifier, final String json) { - if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } - - final Type typeOfMap = new TypeToken>() {}.getType(); - final Map requestMap = gsonConverter.fromJson(json, typeOfMap); - - final Set supportedParams = new HashSet(Arrays.asList("name", "officeId", "levelId", "parentId", "staffId", - "externalId", "clientMembers")); - - checkForUnsupportedParameters(requestMap, supportedParams); - - final Set modifiedParameters = new HashSet(); - - final String name = extractStringParameter("name", requestMap, modifiedParameters); - final Long officeId = extractLongParameter("officeId", requestMap, modifiedParameters); - final Long levelId = extractLongParameter("levelId", requestMap, modifiedParameters); - final Long parentId = extractLongParameter("parentId", requestMap, modifiedParameters); - final Long staffId = extractLongParameter("staffId", requestMap, modifiedParameters); - final String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); - - final JsonParser parser = new JsonParser(); - - String[] clientMembers = null; - JsonElement element = parser.parse(json); - if (element.isJsonObject()) { - JsonObject object = element.getAsJsonObject(); - if (object.has("clientMembers")) { - modifiedParameters.add("clientMembers"); - JsonArray array = object.get("clientMembers").getAsJsonArray(); - clientMembers = new String[array.size()]; - for (int i = 0; i < array.size(); i++) { - clientMembers[i] = array.get(i).getAsString(); - } - } - } - - return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name, officeId, staffId, clientMembers, parentId, - levelId); - } - - private void checkForUnsupportedParameters(final Map requestMap, final Set supportedParams) { - List unsupportedParameterList = new ArrayList(); - for (String providedParameter : requestMap.keySet()) { - if (!supportedParams.contains(providedParameter)) { - unsupportedParameterList.add(providedParameter); - } - } - - if (!unsupportedParameterList.isEmpty()) { throw new UnsupportedParameterException(unsupportedParameterList); } - } - - private String extractStringParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { - String paramValue = null; - if (requestMap.containsKey(paramName)) { - paramValue = (String) requestMap.get(paramName); - modifiedParameters.add(paramName); - } - - if (paramValue != null) { - paramValue = paramValue.trim(); - } - - return paramValue; - } - - private Long extractLongParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { - Long paramValue = null; - if (requestMap.containsKey(paramName)) { - String valueAsString = (String) requestMap.get(paramName); - if (StringUtils.isNotBlank(valueAsString)) { - paramValue = Long.valueOf(Double.valueOf(valueAsString).longValue()); - } - modifiedParameters.add(paramName); - } - return paramValue; - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/api/GroupsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/api/GroupsApiResource.java index e54d1551e..fdbf7e228 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/api/GroupsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/api/GroupsApiResource.java @@ -24,18 +24,18 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; +import org.mifosplatform.commands.domain.CommandWrapper; +import org.mifosplatform.commands.service.CommandWrapperBuilder; +import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; -import org.mifosplatform.portfolio.group.PortfolioApiDataConversionService; -import org.mifosplatform.portfolio.group.command.GroupCommand; import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData; import org.mifosplatform.portfolio.group.data.GroupData; import org.mifosplatform.portfolio.group.service.GroupReadPlatformService; -import org.mifosplatform.portfolio.group.service.GroupWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -46,32 +46,27 @@ import org.springframework.stereotype.Component; public class GroupsApiResource { private static final Set GROUP_DATA_PARAMETERS = new HashSet(Arrays.asList("id", "officeId", "name", "externalId", - "clientMembers", "allowedClients", "allowedOffices" , "allowedParentGroups" ,"groupLevel" ,"allowedStaffs" ,"childGroups")); - + "clientMembers", "allowedClients", "allowedOffices", "allowedParentGroups", "groupLevel", "allowedStaffs", "childGroups")); + private final PlatformSecurityContext context; private final GroupReadPlatformService groupReadPlatformService; - private final GroupWritePlatformService groupWritePlatformService; private final ToApiJsonSerializer toApiJsonSerializer; private final ToApiJsonSerializer groupSummaryToApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; - private final PortfolioApiDataConversionService apiDataConversionService; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @Autowired - public GroupsApiResource( - final PlatformSecurityContext context, - final GroupReadPlatformService groupReadPlatformService, - final GroupWritePlatformService groupWritePlatformService, + public GroupsApiResource(final PlatformSecurityContext context, final GroupReadPlatformService groupReadPlatformService, final ToApiJsonSerializer toApiJsonSerializer, final ToApiJsonSerializer groupSummaryToApiJsonSerializer, - final ApiRequestParameterHelper apiRequestParameterHelper, - final PortfolioApiDataConversionService apiDataConversionService) { + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; this.groupReadPlatformService = groupReadPlatformService; - this.groupWritePlatformService = groupWritePlatformService; this.toApiJsonSerializer = toApiJsonSerializer; this.groupSummaryToApiJsonSerializer = groupSummaryToApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; - this.apiDataConversionService = apiDataConversionService; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; } @GET @@ -81,12 +76,12 @@ public class GroupsApiResource { @QueryParam("officeId") final Long officeId, @QueryParam("externalId") final String externalId, @QueryParam("name") final String name, @QueryParam("underHierarchy") final String hierarchy) { - context.authenticatedUser().validateHasReadPermission("GROUP"); + this.context.authenticatedUser().validateHasReadPermission("GROUP"); final String extraCriteria = getGroupExtraCriteria(sqlSearch, officeId, externalId, name, hierarchy); - Collection groups = this.groupReadPlatformService.retrieveAllGroups(extraCriteria); + final Collection groups = this.groupReadPlatformService.retrieveAllGroups(extraCriteria); - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializer.serialize(settings, groups, GROUP_DATA_PARAMETERS); } @@ -96,12 +91,12 @@ public class GroupsApiResource { @Produces({ MediaType.APPLICATION_JSON }) public String retrieveGroupData(@Context final UriInfo uriInfo, @PathParam("groupId") final Long groupId) { - context.authenticatedUser().validateHasReadPermission("GROUP"); - - boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters()); - GroupData group = this.groupReadPlatformService.retrieveGroupDetails(groupId, template); - - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + this.context.authenticatedUser().validateHasReadPermission("GROUP"); + + final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters()); + final GroupData group = this.groupReadPlatformService.retrieveGroupDetails(groupId, template); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializer.serialize(settings, group, GROUP_DATA_PARAMETERS); } @@ -112,7 +107,7 @@ public class GroupsApiResource { public String newGroupDetails(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId, @QueryParam("levelId") final Long levelId, @QueryParam("parentGroupId") final Long parentGroupId) { - context.authenticatedUser().validateHasReadPermission("GROUP"); + this.context.authenticatedUser().validateHasReadPermission("GROUP"); GroupData groupTemplateData = null; if (levelId != null && parentGroupId != null) { @@ -120,63 +115,55 @@ public class GroupsApiResource { } else if (officeId != null && levelId != null) { groupTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(officeId, levelId); } else if (levelId != null) { - groupTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(context.authenticatedUser().getOffice().getId(), + groupTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(this.context.authenticatedUser().getOffice().getId(), levelId); } - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializer.serialize(settings, groupTemplateData, GROUP_DATA_PARAMETERS); } @POST @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String createGroup(final String jsonRequestBody) { + public String createGroup(final String apiRequestBodyAsJson) { - final GroupCommand command = this.apiDataConversionService.convertJsonToGroupCommand(null, jsonRequestBody); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .createGroup() // + .withJson(apiRequestBodyAsJson) // + .build(); // + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); - CommandProcessingResult entityIdentifier = this.groupWritePlatformService.createGroup(command); - - return this.toApiJsonSerializer.serialize(entityIdentifier); - } - - @POST - @Path("{groupId}/command/assign_staff") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String assignLoanOfficer(@PathParam("groupId") final Long groupId, final String jsonRequestBody) { - - final GroupCommand command = this.apiDataConversionService.convertJsonToGroupCommand(groupId, jsonRequestBody); - - CommandProcessingResult entityIdentifier = this.groupWritePlatformService.assignStaff(command); - - return this.toApiJsonSerializer.serialize(entityIdentifier); } @POST @Path("{groupId}/command/unassign_staff") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String unassignLoanOfficer(@PathParam("groupId") final Long groupId, final String jsonRequestBody) { + public String unassignLoanOfficer(@PathParam("groupId") final Long groupId, final String apiRequestBodyAsJson) { - final GroupCommand command = this.apiDataConversionService.convertJsonToGroupCommand(groupId, jsonRequestBody); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .unassignStaff(groupId) // + .withJson(apiRequestBodyAsJson) // + .build(); // + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); - CommandProcessingResult entityIdentifier = this.groupWritePlatformService.unassignStaff(command); - - return this.toApiJsonSerializer.serialize(entityIdentifier); } @PUT @Path("{groupId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String updateGroup(@PathParam("groupId") final Long groupId, final String jsonRequestBody) { + public String updateGroup(@PathParam("groupId") final Long groupId, final String apiRequestBodyAsJson) { - final GroupCommand command = this.apiDataConversionService.convertJsonToGroupCommand(groupId, jsonRequestBody); - - CommandProcessingResult entityIdentifier = this.groupWritePlatformService.updateGroup(command); - - return this.toApiJsonSerializer.serialize(entityIdentifier); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .updateGroup(groupId) // + .withJson(apiRequestBodyAsJson) // + .build(); // + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); } @DELETE @@ -185,9 +172,12 @@ public class GroupsApiResource { @Produces({ MediaType.APPLICATION_JSON }) public String deleteGroup(@PathParam("groupId") final Long groupId) { - CommandProcessingResult entityIdentifier = this.groupWritePlatformService.deleteGroup(groupId); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .deleteGroup(groupId) // + .build(); // + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); - return this.toApiJsonSerializer.serialize(entityIdentifier); } @GET @@ -196,22 +186,23 @@ public class GroupsApiResource { @Produces({ MediaType.APPLICATION_JSON }) public String retrieveGroupAccount(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission("GROUP"); + this.context.authenticatedUser().validateHasReadPermission("GROUP"); + + final GroupAccountSummaryCollectionData groupAccount = this.groupReadPlatformService.retrieveGroupAccountDetails(groupId); - GroupAccountSummaryCollectionData groupAccount = this.groupReadPlatformService.retrieveGroupAccountDetails(groupId); - final Set GROUP_ACCOUNTS_DATA_PARAMETERS = new HashSet(Arrays.asList("pendingApprovalLoans", - "awaitingDisbursalLoans", "openLoans", "closedLoans", "anyLoanCount", "pendingApprovalLoanCount", "awaitingDisbursalLoanCount", - "activeLoanCount", "closedLoanCount")); + "awaitingDisbursalLoans", "openLoans", "closedLoans", "anyLoanCount", "pendingApprovalLoanCount", + "awaitingDisbursalLoanCount", "activeLoanCount", "closedLoanCount")); - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.groupSummaryToApiJsonSerializer.serialize(settings, groupAccount, GROUP_ACCOUNTS_DATA_PARAMETERS); } // 'g.' preffix because of ERROR 1052 (23000): Column 'column_name' in where // clause is ambiguous // caused by the same name of columns in m_office and m_group tables - private String getGroupExtraCriteria(String sqlSearch, final Long officeId, final String externalId, final String name, final String hierarchy) { + private String getGroupExtraCriteria(String sqlSearch, final Long officeId, final String externalId, final String name, + final String hierarchy) { String extraCriteria = ""; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommand.java index ecf067a90..5903a1881 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommand.java @@ -5,94 +5,54 @@ */ package org.mifosplatform.portfolio.group.command; -import java.util.Set; - public class GroupCommand { - private final Long id; private final String externalId; private final String name; private final Long officeId; private final Long staffId; private final Long parentId; - private final Long levelId; - private final String[] clientMembers; + private final String[] childGroups; - private final Set modifiedParameters; - - public GroupCommand(Set modifiedParameters, final Long id, final String externalId, final String name, - final Long officeId, final Long staffId, String[] clientMembers , final Long parentId ,final Long levelId) { - this.id = id; + public GroupCommand(final String externalId, final String name, final Long officeId, final Long staffId, final String[] clientMembers, + final String[] childGroups, final Long parentId) { this.officeId = officeId; this.staffId = staffId; this.parentId = parentId; - this.levelId = levelId; this.externalId = externalId; this.name = name; this.clientMembers = clientMembers; - this.modifiedParameters = modifiedParameters; - + this.childGroups = childGroups; + } public Long getOfficeId() { - return officeId; + return this.officeId; } public Long getParentId() { - return parentId; - } - - public Long getLevelId() { - return levelId; + return this.parentId; } public Long getStaffId() { - return staffId; + return this.staffId; } - + public String getExternalId() { - return externalId; + return this.externalId; } public String getName() { - return name; - } - - public Long getId() { - return id; + return this.name; } public String[] getClientMembers() { - return clientMembers; + return this.clientMembers; } - public boolean isOfficeIdChanged() { - return this.modifiedParameters.contains("officeId"); + public String[] getChildGroups() { + return this.childGroups; } - public boolean isParentIdChanged() { - return this.modifiedParameters.contains("parentId"); - } - - public boolean isLevelIdChanged() { - return this.modifiedParameters.contains("levelId"); - } - - public boolean isStaffChanged() { - return this.modifiedParameters.contains("staffId"); - } - - public boolean isNameChanged() { - return this.modifiedParameters.contains("name"); - } - - public boolean isExternalIdChanged() { - return this.modifiedParameters.contains("externalId"); - } - - public boolean isClientMembersChanged() { - return this.modifiedParameters.contains("clientMembers"); - } - -} +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommandValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommandValidator.java deleted file mode 100644 index a24414c7c..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/command/GroupCommandValidator.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.group.command; - -import java.util.ArrayList; -import java.util.List; - -import org.mifosplatform.infrastructure.core.data.ApiParameterError; -import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; -import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; - -public class GroupCommandValidator { - - private final GroupCommand command; - - public GroupCommandValidator(GroupCommand command) { - this.command = command; - } - - public void validateForCreate() { - - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group"); - - baseDataValidator.reset().parameter("name").value(command.getName()).notBlank(); - baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); - baseDataValidator.reset().parameter("officeId").value(command.getOfficeId()).notNull().integerGreaterThanZero(); - baseDataValidator.reset().parameter("levelId").value(command.getLevelId()).notNull().integerGreaterThanZero(); - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); - } - } - - public void validateForUpdate() { - - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group"); - - baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); - baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank(); - baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); - - if (command.isOfficeIdChanged()) { - baseDataValidator.reset().parameter("officeId").value(command.getOfficeId()).notNull().integerGreaterThanZero(); - } - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); - } - } - - public void validateForStaffUpdate() { - - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group"); - - baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); - - if (command.isStaffChanged()) { - baseDataValidator.reset().parameter("staffId").value(command.getStaffId()).notNull().integerGreaterThanZero(); - } - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); - } - } - -} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryCollectionData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryCollectionData.java index adbb661b0..c5f29e3e9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryCollectionData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryCollectionData.java @@ -34,11 +34,11 @@ public class GroupAccountSummaryCollectionData { @SuppressWarnings("unused") private final List closedIndividualLoans; - public GroupAccountSummaryCollectionData(List pendingApprovalLoans, - List awaitingDisbursalLoans, List openLoans, - List closedLoans, List pendingApprovalIndividualLoans, - List awaitingDisbursalIndividualLoans, List openIndividualLoans, - List closedIndividualLoans) { + public GroupAccountSummaryCollectionData(final List pendingApprovalLoans, + final List awaitingDisbursalLoans, final List openLoans, + final List closedLoans, final List pendingApprovalIndividualLoans, + final List awaitingDisbursalIndividualLoans, final List openIndividualLoans, + final List closedIndividualLoans) { this.pendingApprovalLoans = pendingApprovalLoans; this.pendingApprovalLoanCount = pendingApprovalLoans.size(); this.awaitingDisbursalLoans = awaitingDisbursalLoans; @@ -48,7 +48,7 @@ public class GroupAccountSummaryCollectionData { this.closedLoans = closedLoans; this.closedLoanCount = closedLoans.size(); - this.anyLoanCount = pendingApprovalLoanCount + awaitingDisbursalLoanCount + activeLoanCount + closedLoanCount; + this.anyLoanCount = this.pendingApprovalLoanCount + this.awaitingDisbursalLoanCount + this.activeLoanCount + this.closedLoanCount; this.pendingApprovalIndividualLoans = pendingApprovalIndividualLoans; this.pendingApprovalIndividualLoanCount = pendingApprovalIndividualLoans.size(); @@ -59,43 +59,43 @@ public class GroupAccountSummaryCollectionData { this.closedIndividualLoans = closedIndividualLoans; this.closedIndividualLoanCount = closedIndividualLoans.size(); - this.anyIndividualLoanCount = pendingApprovalIndividualLoanCount + awaitingDisbursalIndividualLoanCount + activeIndividualLoanCount - + closedIndividualLoanCount; + this.anyIndividualLoanCount = this.pendingApprovalIndividualLoanCount + this.awaitingDisbursalIndividualLoanCount + + this.activeIndividualLoanCount + this.closedIndividualLoanCount; } public int getAnyLoanCount() { - return anyLoanCount; + return this.anyLoanCount; } public int getPendingApprovalLoanCount() { - return pendingApprovalLoanCount; + return this.pendingApprovalLoanCount; } public List getPendingApprovalLoans() { - return pendingApprovalLoans; + return this.pendingApprovalLoans; } public int getAwaitingDisbursalLoanCount() { - return awaitingDisbursalLoanCount; + return this.awaitingDisbursalLoanCount; } public List getAwaitingDisbursalLoans() { - return awaitingDisbursalLoans; + return this.awaitingDisbursalLoans; } public int getActiveLoanCount() { - return activeLoanCount; + return this.activeLoanCount; } public List getOpenLoans() { - return openLoans; + return this.openLoans; } public int getClosedLoanCount() { - return closedLoanCount; + return this.closedLoanCount; } public List getClosedLoans() { - return closedLoans; + return this.closedLoans; } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryData.java index 3e5cd7b84..7695d50ee 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupAccountSummaryData.java @@ -16,10 +16,8 @@ public class GroupAccountSummaryData { private final String productName; private final Integer accountStatusId; - public GroupAccountSummaryData(Long id, String externalId, - Long productId, - String productName, - Integer accountStatusId) { + public GroupAccountSummaryData(final Long id, final String externalId, final Long productId, final String productName, + final Integer accountStatusId) { this.id = id; this.externalId = externalId; this.productId = productId; @@ -28,22 +26,22 @@ public class GroupAccountSummaryData { } public Long getId() { - return id; + return this.id; } public String getExternalId() { - return externalId; + return this.externalId; } public Long getProductId() { - return productId; + return this.productId; } public String getProductName() { - return productName; + return this.productName; } public Integer getAccountStatusId() { - return accountStatusId; + return this.accountStatusId; } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupData.java index 940c40ed4..a0c1e3adc 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupData.java @@ -44,7 +44,8 @@ public class GroupData { private final Collection childGroups; public GroupData(final Long id, final Long officeId, final String officeName, final String name, final String externalId, - final Long groupLevel, final Long parentId, final String parentName, final Long staffId, final String staffName , final String hierarchy) { + final Long groupLevel, final Long parentId, final String parentName, final Long staffId, final String staffName, + final String hierarchy) { this.id = id; this.officeId = officeId; this.officeName = officeName; @@ -68,7 +69,8 @@ public class GroupData { public GroupData(final GroupData group, final Collection clientMembers, final Collection allowedClients, final Collection allowedOffices, final Collection allowedParentGroups, - final GroupLevelData groupLevelData, final Collection allowedStaffs, final Collection childGroups , final GroupSummaryData groupSummaryData) { + final GroupLevelData groupLevelData, final Collection allowedStaffs, final Collection childGroups, + final GroupSummaryData groupSummaryData) { this.id = group.getId(); this.officeId = group.getOfficeId(); this.officeName = group.getOfficeName(); @@ -116,23 +118,23 @@ public class GroupData { } public Long getId() { - return id; + return this.id; } public String getName() { - return name; + return this.name; } public String getExternalId() { - return externalId; + return this.externalId; } public Long getOfficeId() { - return officeId; + return this.officeId; } public String getOfficeName() { - return officeName; + return this.officeName; } public Long getGroupLevel() { @@ -155,7 +157,6 @@ public class GroupData { return this.parentName; } - public String getHierarchy() { return this.hierarchy; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLevelData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLevelData.java index d154823ff..e4b95ab5a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLevelData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLevelData.java @@ -10,7 +10,6 @@ package org.mifosplatform.portfolio.group.data; */ public class GroupLevelData { - private final Long levelId; private final String levelName; private final Long parentLevelId; @@ -20,9 +19,10 @@ public class GroupLevelData { private final boolean superParent; private final boolean recursable; private final boolean canHaveClients; - - public GroupLevelData(Long levelId, String levelName, Long parentLevelId, String parentLevelName, Long childLevelId, - String childLevelName, boolean superParent, boolean recursable, boolean canHaveClients) { + + public GroupLevelData(final Long levelId, final String levelName, final Long parentLevelId, final String parentLevelName, + final Long childLevelId, final String childLevelName, final boolean superParent, final boolean recursable, + final boolean canHaveClients) { super(); this.levelId = levelId; this.levelName = levelName; @@ -35,50 +35,38 @@ public class GroupLevelData { this.canHaveClients = canHaveClients; } - - public String getParentLevelName() { return this.parentLevelName; } - - public Long getChildLevelId() { return this.childLevelId; } - - public String getChildLevelName() { return this.childLevelName; } - public Long getLevelId() { return this.levelId; } - public Long getParentLevelId() { return this.parentLevelId; } - public String getLevelName() { return this.levelName; } - public boolean isSuperParent() { return this.superParent; } - public boolean isRecursable() { return this.recursable; } - public boolean isCanHaveClients() { return this.canHaveClients; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLookupData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLookupData.java index 34376880f..557a7415c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLookupData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupLookupData.java @@ -19,10 +19,10 @@ public class GroupLookupData { } public Long getId() { - return id; + return this.id; } public String getName() { - return name; + return this.name; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/Group.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/Group.java index 00a995a7d..947729131 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/Group.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/Group.java @@ -24,7 +24,6 @@ import org.apache.commons.lang.StringUtils; import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.portfolio.client.domain.Client; -import org.mifosplatform.portfolio.group.command.GroupCommand; import org.springframework.data.jpa.domain.AbstractPersistable; @Entity @@ -46,9 +45,10 @@ public class Group extends AbstractPersistable { @ManyToOne @JoinColumn(name = "staff_id", nullable = true) private Staff staff; - - @Column(name = "level_id", nullable = false) - private Long levelId; + + @ManyToOne + @JoinColumn(name = "level_id", nullable = false) + private GroupLevel groupLevel; @Column(name = "hierarchy", length = 100) private String hierarchy; @@ -72,20 +72,22 @@ public class Group extends AbstractPersistable { this.clientMembers = new HashSet(); } - public static Group newGroup(final Office office, final Staff staff , final Group parent ,final long levelId , final String name, final String externalId, final Set clientMembers) { - return new Group(office, staff , parent , levelId , name, externalId, clientMembers); + public static Group newGroup(final Office office, final Staff staff, final Group parent, final GroupLevel groupLevel, + final String name, final String externalId, final Set clientMembers, final Set childGroups) { + return new Group(office, staff, parent, groupLevel, name, externalId, clientMembers, childGroups); } - public Group(final Office office, final Staff staff , final Group parent ,final long levelId , final String name, final String externalId, final Set clientMembers) { + public Group(final Office office, final Staff staff, final Group parent, final GroupLevel groupLevel, final String name, + final String externalId, final Set clientMembers, final Set childGroups) { this.office = office; this.staff = staff; - this.levelId =levelId; + this.groupLevel = groupLevel; this.parent = parent; - + if (parent != null) { this.parent.addChild(this); } - + if (StringUtils.isNotBlank(name)) { this.name = name.trim(); } else { @@ -99,6 +101,9 @@ public class Group extends AbstractPersistable { if (clientMembers != null) { this.clientMembers = clientMembers; } + if (childGroups != null) { + this.children.addAll(childGroups); + } } private void addChild(final Group group) { @@ -109,12 +114,10 @@ public class Group extends AbstractPersistable { return this.office.getId(); } - public Staff getStaff() { return this.staff; } - public void setStaff(final Staff staff) { this.staff = staff; } @@ -123,48 +126,52 @@ public class Group extends AbstractPersistable { return this.staff.getId(); } - - public Long getLevelId() { - return this.levelId; + public GroupLevel getGroupLevel() { + return this.groupLevel; } - - public void setLevelId(final Long levelId) { - this.levelId = levelId; + public String getExternalId() { + return this.externalId; } - public void update(final GroupCommand command, final Office groupOffice, final Staff staff, final Set clientMembers) { - if (command.isExternalIdChanged()) { - this.externalId = command.getExternalId(); - } - - if (command.isOfficeIdChanged()) { - this.office = groupOffice; - } - - if (command.isStaffChanged()) { - this.staff = staff; - } - - if (command.isNameChanged()) { - this.name = command.getName(); - } - - if (clientMembers != null && command.isClientMembersChanged()) { - this.clientMembers = clientMembers; - } + public String getName() { + return this.name; } - public void assigStaff(final GroupCommand command , final Staff newStaff){ - if (command.isStaffChanged()) { - this.staff = newStaff; - } + public Set getClientMembers() { + return this.clientMembers; } - public void unassigStaff(final GroupCommand command) { - if (command.isStaffChanged()) { - this.staff = null; - } + public Group getParent() { + return this.parent; + } + + public void setParent(final Group parent) { + this.parent = parent; + } + + public void setClientMembers(final Set clientMembers) { + this.clientMembers = clientMembers; + } + + public void setName(final String name) { + this.name = name; + } + + public void setExternalId(final String externalId) { + this.externalId = externalId; + } + + public void setLevelId(final GroupLevel groupLevel) { + this.groupLevel = groupLevel; + } + + public void assigStaff(final Staff newStaff) { + this.staff = newStaff; + } + + public void unassigStaff() { + this.staff = null; } public void addClientMember(final Client member) { @@ -183,20 +190,20 @@ public class Group extends AbstractPersistable { */ public void delete() { this.deleted = true; - this.externalId = this.getId() + "_" + this.externalId; - this.name = this.getId() + "_" + this.name; + this.externalId = getId() + "_" + this.externalId; + this.name = getId() + "_" + this.name; } public boolean isDeleted() { - return deleted; + return this.deleted; } - + public void generateHierarchy() { - if (parent != null) { - this.hierarchy = this.parent.hierarchyOf(this.getId()); + if (this.parent != null) { + this.hierarchy = this.parent.hierarchyOf(getId()); } else { - this.hierarchy = "." + this.getId() + "."; + this.hierarchy = "." + getId() + "."; } } @@ -204,4 +211,8 @@ public class Group extends AbstractPersistable { return this.hierarchy + id.toString() + "."; } + public boolean isOfficeIdentifiedBy(final Long officeId) { + return this.office.identifiedBy(officeId); + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevel.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevel.java index 29965b530..0f32ab9c7 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevel.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevel.java @@ -55,25 +55,24 @@ public class GroupLevel extends AbstractPersistable { return this.parentId; } - public boolean getIsSuperParent() { - return this.superParent; - } - public String getLevelName() { return this.levelName; } - public boolean getRecursable() { + public boolean isRecursable() { return this.recursable; } - public boolean getCanHaveClients() { + public boolean canHaveClients() { return this.canHaveClients; } - public boolean isSuperParent() { return this.superParent; } + public boolean isIdentifiedByParentId(final Long parentLevelId) { + return this.parentId.equals(parentLevelId); + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevelRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevelRepository.java index 1fcbc2849..7efd1c62b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevelRepository.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupLevelRepository.java @@ -9,5 +9,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; public interface GroupLevelRepository extends JpaRepository, JpaSpecificationExecutor { - // no behaviour added + + GroupLevel findBySuperParent(boolean superParent); + + GroupLevel findByParentId(Long parentId); + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/LoanOfficerNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupHasNoStaffException.java similarity index 63% rename from mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/LoanOfficerNotFoundException.java rename to mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupHasNoStaffException.java index 3ec40fc7f..6d1eb2df1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/LoanOfficerNotFoundException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupHasNoStaffException.java @@ -10,10 +10,10 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN /** * A {@link RuntimeException} thrown when group resources are not found. */ -public class LoanOfficerNotFoundException extends AbstractPlatformResourceNotFoundException { +public class GroupHasNoStaffException extends AbstractPlatformResourceNotFoundException { - public LoanOfficerNotFoundException(Long id){ - super("error.msg.loanofficer.id.invalid", "Loan Officer with identifier " + id + " does not exist", id); + public GroupHasNoStaffException(final Long groupId) { + super("error.msg.group.has.no.staff", "Group with identifier " + groupId + " does not have staff", groupId); } - + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupLevelNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupLevelNotFoundException.java index 945fe079f..4890dabde 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupLevelNotFoundException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupLevelNotFoundException.java @@ -12,8 +12,8 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN */ public class GroupLevelNotFoundException extends AbstractPlatformResourceNotFoundException { - public GroupLevelNotFoundException(Long id){ + public GroupLevelNotFoundException(final Long id) { super("error.msg.group.level.id.invalid", "Group level with identifier " + id + " does not exist", id); } - + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupNotFoundException.java index c38453b55..c5147cc72 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupNotFoundException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/GroupNotFoundException.java @@ -12,8 +12,8 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN */ public class GroupNotFoundException extends AbstractPlatformResourceNotFoundException { - public GroupNotFoundException(Long id){ + public GroupNotFoundException(final Long id) { super("error.msg.group.id.invalid", "Group with identifier " + id + " does not exist", id); } - + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/InvalidGroupLevelException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/InvalidGroupLevelException.java index 2248c0d03..1476b942b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/InvalidGroupLevelException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/exception/InvalidGroupLevelException.java @@ -8,12 +8,14 @@ package org.mifosplatform.portfolio.group.exception; import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException; /** - * {@link AbstractPlatformDomainRuleException} thrown when parentGroup'd level is not equal to parent level of the levelid param,. + * {@link AbstractPlatformDomainRuleException} thrown when parentGroup'd level + * is not equal to parent level of the levelid param,. */ public class InvalidGroupLevelException extends AbstractPlatformDomainRuleException { - public InvalidGroupLevelException(final String action, String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) { + public InvalidGroupLevelException(final String action, final String postFix, final String defaultUserMessage, + final Object... defaultUserMessageArgs) { super("error.msg.group." + action + "." + postFix, defaultUserMessage, defaultUserMessageArgs); -} - + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/CreateGroupCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/CreateGroupCommandHandler.java new file mode 100644 index 000000000..dd8454ba0 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/CreateGroupCommandHandler.java @@ -0,0 +1,32 @@ +/** + * 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.group.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.group.service.GroupWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CreateGroupCommandHandler implements NewCommandSourceHandler { + + private final GroupWritePlatformService groupWritePlatformService; + + @Autowired + public CreateGroupCommandHandler(final GroupWritePlatformService groupWritePlatformService) { + this.groupWritePlatformService = groupWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.groupWritePlatformService.createGroup(command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/DeleteGroupCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/DeleteGroupCommandHandler.java new file mode 100644 index 000000000..9099cdd30 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/DeleteGroupCommandHandler.java @@ -0,0 +1,31 @@ +/** + * 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.group.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.group.service.GroupWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class DeleteGroupCommandHandler implements NewCommandSourceHandler { + + private final GroupWritePlatformService groupWritePlatformService; + + @Autowired + public DeleteGroupCommandHandler(final GroupWritePlatformService groupWritePlatformService) { + this.groupWritePlatformService = groupWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.groupWritePlatformService.deleteGroup(command.entityId()); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/UnassignStaffCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/UnassignStaffCommandHandler.java new file mode 100644 index 000000000..e651a8a1f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/UnassignStaffCommandHandler.java @@ -0,0 +1,31 @@ +/** + * 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.group.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.group.service.GroupWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class UnassignStaffCommandHandler implements NewCommandSourceHandler { + + private final GroupWritePlatformService groupWritePlatformService; + + @Autowired + public UnassignStaffCommandHandler(final GroupWritePlatformService groupWritePlatformService) { + this.groupWritePlatformService = groupWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.groupWritePlatformService.unassignStaff(command.entityId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/UpdateGroupCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/UpdateGroupCommandHandler.java new file mode 100644 index 000000000..347101c6e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/handler/UpdateGroupCommandHandler.java @@ -0,0 +1,32 @@ +/** + * 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.group.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.group.service.GroupWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class UpdateGroupCommandHandler implements NewCommandSourceHandler { + + private final GroupWritePlatformService groupWritePlatformService; + + @Autowired + public UpdateGroupCommandHandler(final GroupWritePlatformService groupWritePlatformService) { + this.groupWritePlatformService = groupWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.groupWritePlatformService.updateGroup(command.entityId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/serialization/GroupCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/serialization/GroupCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..92f86083d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/serialization/GroupCommandFromApiJsonDeserializer.java @@ -0,0 +1,179 @@ +/** + * 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.group.serialization; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; +import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.portfolio.client.command.ClientCommand; +import org.mifosplatform.portfolio.group.command.GroupCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; + +/** + * Implementation of {@link FromApiJsonDeserializer} for {@link ClientCommand} + * 's. + */ +@Component +public final class GroupCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { + + /** + * The parameters supported for this command. + */ + private final Set supportedParameters = new HashSet(Arrays.asList("id", "externalId", "name", "officeId", "staffId", + "parentId", "clientMembers", "childGroups")); + + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public GroupCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + @Override + public GroupCommand commandFromApiJson(final String json) { + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element); + final String name = this.fromApiJsonHelper.extractStringNamed("name", element); + final Long officeId = this.fromApiJsonHelper.extractLongNamed("officeId", element); + final Long staffId = this.fromApiJsonHelper.extractLongNamed("staffId", element); + final Long parentId = this.fromApiJsonHelper.extractLongNamed("parentId", element); + final String[] clientMembers = this.fromApiJsonHelper.extractArrayNamed("clientMembers", element); + final String[] childGroups = this.fromApiJsonHelper.extractArrayNamed("childGroups", element); + + return new GroupCommand(externalId, name, officeId, staffId, clientMembers, childGroups, parentId); + } + + public void validateForCreate(final String json) { + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters); + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final List dataValidationErrors = new ArrayList(); + + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group"); + + final String externalIdParameterName = "externalId"; + if (this.fromApiJsonHelper.parameterExists(externalIdParameterName, element)) { + final String externalId = this.fromApiJsonHelper.extractStringNamed(externalIdParameterName, element); + baseDataValidator.reset().parameter(externalIdParameterName).value(externalId).ignoreIfNull().notExceedingLengthOf(100); + } + + final String officeIdParameterName = "officeId"; + if (this.fromApiJsonHelper.parameterExists(officeIdParameterName, element)) { + final Long officeId = this.fromApiJsonHelper.extractLongNamed(officeIdParameterName, element); + baseDataValidator.reset().parameter(officeIdParameterName).value(officeId).notNull().integerGreaterThanZero(); + } + + final String parentIdParameterName = "parentId"; + if (this.fromApiJsonHelper.parameterExists(parentIdParameterName, element)) { + final Long parentId = this.fromApiJsonHelper.extractLongNamed(parentIdParameterName, element); + baseDataValidator.reset().parameter(parentIdParameterName).value(parentId).notNull().integerGreaterThanZero(); + } + + final String staffIdParameterName = "stafftId"; + if (this.fromApiJsonHelper.parameterExists(staffIdParameterName, element)) { + final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element); + baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().integerGreaterThanZero(); + } + + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } + } + + public void validateForUpdate(final String json) { + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + + /* + * Office updated is not supported + */ + final Set supportedParametersForupdate = new HashSet(Arrays.asList("id", "externalId", "name", "staffId", + "parentId", "clientMembers", "childGroups")); + + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersForupdate); + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final List dataValidationErrors = new ArrayList(); + + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group"); + + final String externalIdParameterName = "externalId"; + if (this.fromApiJsonHelper.parameterExists(externalIdParameterName, element)) { + final String externalId = this.fromApiJsonHelper.extractStringNamed(externalIdParameterName, element); + baseDataValidator.reset().parameter(externalIdParameterName).value(externalId).ignoreIfNull().notExceedingLengthOf(100); + } + + final String parentIdParameterName = "parentId"; + if (this.fromApiJsonHelper.parameterExists(parentIdParameterName, element)) { + final Long parentId = this.fromApiJsonHelper.extractLongNamed(parentIdParameterName, element); + baseDataValidator.reset().parameter(parentIdParameterName).value(parentId).notNull().integerGreaterThanZero(); + } + + final String staffIdParameterName = "stafftId"; + if (this.fromApiJsonHelper.parameterExists(staffIdParameterName, element)) { + final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element); + baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().integerGreaterThanZero(); + } + + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } + } + + public void validateForUnassignStaff(final String json) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + + /* + * Office updated is not supported + */ + final Set supportedParametersUnassignStaff = new HashSet(Arrays.asList("staffId")); + + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersUnassignStaff); + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final List dataValidationErrors = new ArrayList(); + + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group"); + + final String staffIdParameterName = "stafftId"; + if (this.fromApiJsonHelper.parameterExists(staffIdParameterName, element)) { + final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element); + baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().integerGreaterThanZero(); + } + + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformService.java index 6af5355de..2019a8ef9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformService.java @@ -19,18 +19,18 @@ import org.mifosplatform.portfolio.group.data.GroupLookupData; public interface GroupReadPlatformService { Collection retrieveAllGroups(String extraCriteria); - + GroupData retrieveGroup(Long groupId); - GroupData retrieveNewGroupDetails(Long officeId , Long levelId); + GroupData retrieveNewGroupDetails(Long officeId, Long levelId); Collection retrieveClientMembers(Long groupId); GroupAccountSummaryCollectionData retrieveGroupAccountDetails(Long groupId); Collection retrieveGroupLoanAccountsByLoanOfficerId(Long groupId, Long loanOfficerId); - - Collection retrieveAllGroupsbyOfficeIdAndLevelId(Long officeId , Long levelId); + + Collection retrieveAllGroupsbyOfficeIdAndLevelId(Long officeId, Long levelId); GroupLevelData retrieveGroupLevelDetails(Long levelId); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformServiceImpl.java index 5919be6f1..f642ec6e6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupReadPlatformServiceImpl.java @@ -20,7 +20,6 @@ import org.mifosplatform.organisation.monetary.data.MoneyData; import org.mifosplatform.organisation.office.data.OfficeData; import org.mifosplatform.organisation.office.service.OfficeReadPlatformService; import org.mifosplatform.organisation.staff.data.StaffData; -import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.organisation.staff.exception.StaffNotFoundException; import org.mifosplatform.portfolio.client.data.ClientLookup; import org.mifosplatform.portfolio.client.service.ClientReadPlatformService; @@ -52,7 +51,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { @Autowired public GroupReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource, - ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService, + final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService, final GroupRepository groupRepository) { this.context = context; this.jdbcTemplate = new JdbcTemplate(dataSource); @@ -66,7 +65,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { this.context.authenticatedUser(); - GroupDataMapper rm = new GroupDataMapper(); + final GroupDataMapper rm = new GroupDataMapper(); String sql = "select " + rm.groupSchema() + " where g.is_deleted=0"; @@ -83,12 +82,12 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { try { this.context.authenticatedUser(); - GroupDataMapper rm = new GroupDataMapper(); + final GroupDataMapper rm = new GroupDataMapper(); - String sql = "select " + rm.groupSchema() + " where g.id = ? and g.is_deleted=0"; + final String sql = "select " + rm.groupSchema() + " where g.id = ? and g.is_deleted=0"; return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { groupId }); - } catch (EmptyResultDataAccessException e) { + } catch (final EmptyResultDataAccessException e) { throw new GroupNotFoundException(groupId); } } @@ -97,19 +96,19 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { public Collection retrieveAllGroupsbyOfficeIdAndLevelId(final Long officeId, final Long levelId) { this.context.authenticatedUser(); - GroupLookupMapper rm = new GroupLookupMapper(); - String sql = "select " + rm.groupLookupSchema() + " from m_group g where g.office_id = ? and level_id = ? and g.is_deleted=0"; + final GroupLookupMapper rm = new GroupLookupMapper(); + final String sql = "select " + rm.groupLookupSchema() + " from m_group g where g.office_id = ? and level_id = ? and g.is_deleted=0"; return this.jdbcTemplate.query(sql, rm, new Object[] { officeId, levelId }); } - private GroupLookupData retrieveGroupbyId(Long parentGroupId) { + private GroupLookupData retrieveGroupbyId(final Long parentGroupId) { try { this.context.authenticatedUser(); - GroupLookupMapper rm = new GroupLookupMapper(); - String sql = "select " + rm.groupLookupSchema() + " from m_group g where g.id = ? and g.is_deleted=0"; + final GroupLookupMapper rm = new GroupLookupMapper(); + final String sql = "select " + rm.groupLookupSchema() + " from m_group g where g.id = ? and g.is_deleted=0"; return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { parentGroupId }); - } catch (EmptyResultDataAccessException e) { + } catch (final EmptyResultDataAccessException e) { throw new GroupNotFoundException(parentGroupId); } } @@ -118,8 +117,8 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { public Collection retrieveChildGroupsbyGroupId(final Long groupId) { this.context.authenticatedUser(); - GroupLookupMapper rm = new GroupLookupMapper(); - String sql = "select " + rm.groupLookupSchema() + final GroupLookupMapper rm = new GroupLookupMapper(); + final String sql = "select " + rm.groupLookupSchema() + " from m_group pg join m_group g where pg.id = g.parent_id and pg.id = ? and g.is_deleted=0"; return this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); @@ -131,11 +130,11 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { try { this.context.authenticatedUser(); - GroupLevelDataMapper rm = new GroupLevelDataMapper(); - String sql = "select " + rm.groupLevelSchema() + " where gl.id = ? "; + final GroupLevelDataMapper rm = new GroupLevelDataMapper(); + final String sql = "select " + rm.groupLevelSchema() + " where gl.id = ? "; return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { levelId }); - } catch (EmptyResultDataAccessException e) { + } catch (final EmptyResultDataAccessException e) { throw new GroupLevelNotFoundException(levelId); } } @@ -143,7 +142,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { @Override public GroupData retrieveNewGroupDetails(final Long officeId, final Long levelId) { - GroupLevelData groupLevelData = this.retrieveGroupLevelDetails(levelId); + final GroupLevelData groupLevelData = retrieveGroupLevelDetails(levelId); if (groupLevelData == null) { throw new GroupLevelNotFoundException(levelId); } @@ -154,27 +153,28 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { this.clientReadPlatformService.retrieveAllIndividualClientsForLookupByOfficeId(officeId)); } - List allowedOffices = new ArrayList(officeReadPlatformService.retrieveAllOfficesForDropdown()); + final List allowedOffices = new ArrayList(this.officeReadPlatformService.retrieveAllOfficesForDropdown()); List allowedParentGroups = null; if (groupLevelData.getParentLevelId() != null) { - allowedParentGroups = new ArrayList(this.retrieveAllGroupsbyOfficeIdAndLevelId(officeId, + allowedParentGroups = new ArrayList(retrieveAllGroupsbyOfficeIdAndLevelId(officeId, groupLevelData.getParentLevelId())); } - List allowedStaffs = new ArrayList(this.retrieveStaffsbyOfficeId(officeId)); + final List allowedStaffs = new ArrayList(retrieveStaffsbyOfficeId(officeId)); return new GroupData(officeId, allowedClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs); } @Override - public GroupData retrieveNewChildGroupDetails(Long officeId, Long levelId, Long parentGroupId) { - GroupLevelData groupLevelData = this.retrieveGroupLevelDetails(levelId); + public GroupData retrieveNewChildGroupDetails(Long officeId, final Long levelId, final Long parentGroupId) { + + final GroupLevelData groupLevelData = retrieveGroupLevelDetails(levelId); if (groupLevelData == null) { throw new GroupLevelNotFoundException(levelId); } - Group group = groupRepository.findOne(parentGroupId); - if (group == null) { throw new GroupNotFoundException(parentGroupId); } + final Group group = this.groupRepository.findOne(parentGroupId); + if (group == null || group.isDeleted()) { throw new GroupNotFoundException(parentGroupId); } if (officeId == null) { officeId = group.getOfficeId(); @@ -187,19 +187,14 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { this.clientReadPlatformService.retrieveAllIndividualClientsForLookupByOfficeId(officeId)); } - List allowedOffices = new ArrayList(); - allowedOffices.add(officeReadPlatformService.retrieveOffice(officeId)); + final List allowedOffices = new ArrayList(); + allowedOffices.add(this.officeReadPlatformService.retrieveOffice(officeId)); - List allowedParentGroups = new ArrayList(); - allowedParentGroups.add(this.retrieveGroupbyId(parentGroupId)); + final List allowedParentGroups = new ArrayList(); + allowedParentGroups.add(retrieveGroupbyId(parentGroupId)); - List allowedStaffs = new ArrayList(); - final Staff staff = group.getStaff(); - if (staff == null) { - allowedStaffs.addAll(this.retrieveStaffsbyOfficeId(officeId)); - } else { - allowedStaffs.add(this.retrieveStaffsbyId(staff.getId())); - } + final List allowedStaffs = new ArrayList(); + allowedStaffs.addAll(retrieveStaffsbyOfficeId(officeId)); return new GroupData(officeId, allowedClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs); } @@ -207,21 +202,21 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { @Override public GroupData retrieveGroupDetails(final Long groupId, final boolean template) { - GroupData group = this.retrieveGroup(groupId); - final Collection clientMembers = this.retrieveClientMembers(groupId); + GroupData group = retrieveGroup(groupId); + final Collection clientMembers = retrieveClientMembers(groupId); Collection availableClients = null; Collection allowedOffices = null; Collection allowedParentGroups = null; - GroupLevelData groupLevelData = this.retrieveGroupLevelDetails(group.getGroupLevel()); + final GroupLevelData groupLevelData = retrieveGroupLevelDetails(group.getGroupLevel()); ; Collection allowedStaffs = null; - Collection childGroups = this.retrieveChildGroupsbyGroupId(groupId); + final Collection childGroups = retrieveChildGroupsbyGroupId(groupId); - final Long totalActiveClients = this.retrieveTotalClients(group.getHierarchy()); - final Long totalChildGroups = this.retrieveTotalNoOfChildGroups(groupId); - Collection totalLoanPortfolio = this.retrieveGroupLoanPortfolio(group.getHierarchy()); + final Long totalActiveClients = retrieveTotalClients(group.getHierarchy()); + final Long totalChildGroups = retrieveTotalNoOfChildGroups(groupId); + final Collection totalLoanPortfolio = retrieveGroupLoanPortfolio(group.getHierarchy()); - GroupSummaryData groupSummaryData = new GroupSummaryData(totalActiveClients, totalChildGroups, totalLoanPortfolio, null); + final GroupSummaryData groupSummaryData = new GroupSummaryData(totalActiveClients, totalChildGroups, totalLoanPortfolio, null); group = new GroupData(group, clientMembers, availableClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs, childGroups, groupSummaryData); @@ -232,12 +227,12 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { availableClients = this.clientReadPlatformService.retrieveAllIndividualClientsForLookupByOfficeId(group.getOfficeId()); availableClients.removeAll(group.clientMembers()); } - allowedOffices = officeReadPlatformService.retrieveAllOfficesForDropdown(); + allowedOffices = this.officeReadPlatformService.retrieveAllOfficesForDropdown(); if (groupLevelData.getParentLevelId() != null) { - allowedParentGroups = this.retrieveAllGroupsbyOfficeIdAndLevelId(group.getOfficeId(), groupLevelData.getParentLevelId()); + allowedParentGroups = retrieveAllGroupsbyOfficeIdAndLevelId(group.getOfficeId(), groupLevelData.getParentLevelId()); } - allowedStaffs = this.retrieveStaffsbyOfficeId(group.getOfficeId()); + allowedStaffs = retrieveStaffsbyOfficeId(group.getOfficeId()); group = new GroupData(group, group.clientMembers(), availableClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs, childGroups, groupSummaryData); @@ -250,8 +245,8 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { public Collection retrieveStaffsbyOfficeId(final Long officeId) { this.context.authenticatedUser(); - StaffDataMapper rm = new StaffDataMapper(); - String sql = "select " + rm.staffDataSchema() + " where o.id = ?"; + final StaffDataMapper rm = new StaffDataMapper(); + final String sql = "select " + rm.staffDataSchema() + " where o.id = ?"; return this.jdbcTemplate.query(sql, rm, new Object[] { officeId }); } @@ -261,11 +256,11 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { try { this.context.authenticatedUser(); - StaffDataMapper rm = new StaffDataMapper(); - String sql = "select " + rm.staffDataSchema() + " where s.id = ?"; + final StaffDataMapper rm = new StaffDataMapper(); + final String sql = "select " + rm.staffDataSchema() + " where s.id = ?"; return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { staffId }); - } catch (EmptyResultDataAccessException e) { + } catch (final EmptyResultDataAccessException e) { throw new StaffNotFoundException(staffId); } } @@ -275,19 +270,18 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { this.context.authenticatedUser(); - String groupHierarchy = hierarchy + "%"; - String sqlTotalClients = "SELECT count(gc.client_id) FROM m_group_client gc JOIN m_group g " + final String groupHierarchy = hierarchy + "%"; + final String sqlTotalClients = "SELECT count(gc.client_id) FROM m_group_client gc JOIN m_group g " + "ON gc.group_id = g.id WHERE g.hierarchy LIKE ? "; return this.jdbcTemplate.queryForLong(sqlTotalClients, new Object[] { groupHierarchy }); - // TODO to need catch EmptyResultDataAccessException ? } @Override public Long retrieveTotalNoOfChildGroups(final Long groupId) { this.context.authenticatedUser(); - String sqlTotalClients = "SELECT count(gc.id) FROM m_group g JOIN m_group gc WHERE g.id = gc.parent_id and g.id = ?"; + final String sqlTotalClients = "SELECT count(gc.id) FROM m_group g JOIN m_group gc WHERE g.id = gc.parent_id and g.id = ?"; return this.jdbcTemplate.queryForLong(sqlTotalClients, new Object[] { groupId }); } @@ -297,10 +291,10 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { this.context.authenticatedUser(); - MoneyDataMapper rm = new MoneyDataMapper(); + final MoneyDataMapper rm = new MoneyDataMapper(); - String groupHierarchy = hierarchy + "%"; - String sql = "select " + rm.moneyDataSchema() + " FROM m_group_client gc JOIN m_group g ON gc.group_id = g.id " + final String groupHierarchy = hierarchy + "%"; + final String sql = "select " + rm.moneyDataSchema() + " FROM m_group_client gc JOIN m_group g ON gc.group_id = g.id " + "JOIN m_loan l ON l.client_id = gc.client_id LEFT JOIN m_organisation_currency oc ON oc.code = l.currency_code " + " WHERE g.hierarchy LIKE ? GROUP BY l.currency_code "; @@ -315,11 +309,11 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public MoneyData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException { + public MoneyData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - String currencyCode = rs.getString("currencyCode"); - Integer decimalPlaces = rs.getInt("decimalPlaces"); - BigDecimal amount = rs.getBigDecimal("amount"); + final String currencyCode = rs.getString("currencyCode"); + final Integer decimalPlaces = rs.getInt("decimalPlaces"); + final BigDecimal amount = rs.getBigDecimal("amount"); return new MoneyData(currencyCode, amount, decimalPlaces); } @@ -336,19 +330,19 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public GroupData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException { + public GroupData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - Long id = rs.getLong("id"); - String name = rs.getString("name"); - String externalId = rs.getString("externalId"); - Long officeId = rs.getLong("officeId"); - String officeName = rs.getString("officeName"); - Long groupLevel = rs.getLong("groupLevel"); - Long parentId = rs.getLong("parentId"); - String parentName = rs.getString("parentName"); - Long staffId = rs.getLong("staffId"); - String staffName = rs.getString("staffName"); - String hierarchy = rs.getString("hierarchy"); + final Long id = rs.getLong("id"); + final String name = rs.getString("name"); + final String externalId = rs.getString("externalId"); + final Long officeId = rs.getLong("officeId"); + final String officeName = rs.getString("officeName"); + final Long groupLevel = rs.getLong("groupLevel"); + final Long parentId = rs.getLong("parentId"); + final String parentName = rs.getString("parentName"); + final Long staffId = rs.getLong("staffId"); + final String staffName = rs.getString("staffName"); + final String hierarchy = rs.getString("hierarchy"); return new GroupData(id, officeId, officeName, name, externalId, groupLevel, parentId, parentName, staffId, staffName, hierarchy); @@ -363,10 +357,10 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public GroupLookupData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException { + public GroupLookupData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - Long id = rs.getLong("id"); - String name = rs.getString("name"); + final Long id = rs.getLong("id"); + final String name = rs.getString("name"); return new GroupLookupData(id, name); } @@ -383,17 +377,17 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public GroupLevelData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException { + public GroupLevelData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - Long levelId = rs.getLong("id"); - String levelName = rs.getString("levelName"); - Long parentLevelId = rs.getLong("parentLevelId"); - String parentLevelName = rs.getString("parentName"); - Long childLevelId = rs.getLong("childLevelId"); - String childLevelName = rs.getString("childLevelName"); - boolean superParent = rs.getBoolean("superParent"); - boolean recursable = rs.getBoolean("recursable"); - boolean canHaveClients = rs.getBoolean("canHaveClients"); + final Long levelId = rs.getLong("id"); + final String levelName = rs.getString("levelName"); + final Long parentLevelId = rs.getLong("parentLevelId"); + final String parentLevelName = rs.getString("parentName"); + final Long childLevelId = rs.getLong("childLevelId"); + final String childLevelName = rs.getString("childLevelName"); + final boolean superParent = rs.getBoolean("superParent"); + final boolean recursable = rs.getBoolean("recursable"); + final boolean canHaveClients = rs.getBoolean("canHaveClients"); return new GroupLevelData(levelId, levelName, parentLevelId, parentLevelName, childLevelId, childLevelName, superParent, recursable, canHaveClients); @@ -409,15 +403,15 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public StaffData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException { + public StaffData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - Long id = rs.getLong("id"); - String firstname = rs.getString("firstname"); - String lastname = rs.getString("lastname"); - String displayName = rs.getString("displayName"); - Long officeId = rs.getLong("officeId"); - String officeName = rs.getString("officeName"); - boolean isLoanOfficer = rs.getBoolean("isLoanOfficer"); + final Long id = rs.getLong("id"); + final String firstname = rs.getString("firstname"); + final String lastname = rs.getString("lastname"); + final String displayName = rs.getString("displayName"); + final Long officeId = rs.getLong("officeId"); + final String officeName = rs.getString("officeName"); + final boolean isLoanOfficer = rs.getBoolean("isLoanOfficer"); return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer); } @@ -425,13 +419,13 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public Collection retrieveClientMembers(Long groupId) { + public Collection retrieveClientMembers(final Long groupId) { this.context.authenticatedUser(); - ClientMemberSummaryDataMapper rm = new ClientMemberSummaryDataMapper(); + final ClientMemberSummaryDataMapper rm = new ClientMemberSummaryDataMapper(); - String sql = "select " + rm.clientMemberSummarySchema() + " where cm.is_deleted = 0 and pgc.group_id = ?"; + final String sql = "select " + rm.clientMemberSummarySchema() + " where cm.is_deleted = 0 and pgc.group_id = ?"; return this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); } @@ -443,9 +437,9 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public ClientLookup mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException { - Long id = rs.getLong("id"); - String displayName = rs.getString("displayName"); + public ClientLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { + final Long id = rs.getLong("id"); + final String displayName = rs.getString("displayName"); return ClientLookup.create(id, displayName); } @@ -453,27 +447,27 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } @Override - public GroupAccountSummaryCollectionData retrieveGroupAccountDetails(Long groupId) { + public GroupAccountSummaryCollectionData retrieveGroupAccountDetails(final Long groupId) { try { this.context.authenticatedUser(); // Check if group exists retrieveGroup(groupId); - List pendingApprovalLoans = new ArrayList(); - List awaitingDisbursalLoans = new ArrayList(); - List openLoans = new ArrayList(); - List closedLoans = new ArrayList(); + final List pendingApprovalLoans = new ArrayList(); + final List awaitingDisbursalLoans = new ArrayList(); + final List openLoans = new ArrayList(); + final List closedLoans = new ArrayList(); - GroupLoanAccountSummaryDataMapper rm = new GroupLoanAccountSummaryDataMapper(); + final GroupLoanAccountSummaryDataMapper rm = new GroupLoanAccountSummaryDataMapper(); String sql = "select " + rm.loanAccountSummarySchema() + " where l.group_id = ? and l.client_id is null"; List results = this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); if (results != null) { - for (GroupAccountSummaryData row : results) { + for (final GroupAccountSummaryData row : results) { - LoanStatusMapper statusMapper = new LoanStatusMapper(row.getAccountStatusId()); + final LoanStatusMapper statusMapper = new LoanStatusMapper(row.getAccountStatusId()); if (statusMapper.isOpen()) { openLoans.add(row); @@ -487,18 +481,18 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } } - List pendingApprovalIndividualLoans = new ArrayList(); - List awaitingDisbursalIndividualLoans = new ArrayList(); - List openIndividualLoans = new ArrayList(); - List closedIndividualLoans = new ArrayList(); + final List pendingApprovalIndividualLoans = new ArrayList(); + final List awaitingDisbursalIndividualLoans = new ArrayList(); + final List openIndividualLoans = new ArrayList(); + final List closedIndividualLoans = new ArrayList(); sql = "select " + rm.loanAccountSummarySchema() + " where l.group_id = ? and l.client_id is not null"; results = this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); if (results != null) { - for (GroupAccountSummaryData row : results) { + for (final GroupAccountSummaryData row : results) { - LoanStatusMapper statusMapper = new LoanStatusMapper(row.getAccountStatusId()); + final LoanStatusMapper statusMapper = new LoanStatusMapper(row.getAccountStatusId()); if (statusMapper.isOpen()) { openIndividualLoans.add(row); @@ -514,24 +508,25 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { return new GroupAccountSummaryCollectionData(pendingApprovalLoans, awaitingDisbursalLoans, openLoans, closedLoans, pendingApprovalIndividualLoans, awaitingDisbursalIndividualLoans, openIndividualLoans, closedIndividualLoans); - } catch (EmptyResultDataAccessException e) { + } catch (final EmptyResultDataAccessException e) { throw new GroupNotFoundException(groupId); } } @Override - public Collection retrieveGroupLoanAccountsByLoanOfficerId(Long groupId, Long loanOfficerId) { + public Collection retrieveGroupLoanAccountsByLoanOfficerId(final Long groupId, final Long loanOfficerId) { this.context.authenticatedUser(); // Check if group exists retrieveGroup(groupId); - GroupLoanAccountSummaryDataMapper rm = new GroupLoanAccountSummaryDataMapper(); + final GroupLoanAccountSummaryDataMapper rm = new GroupLoanAccountSummaryDataMapper(); - String sql = "select " + rm.loanAccountSummarySchema() + " where l.group_id = ? and l.client_id is null and l.loan_officer_id = ?"; + final String sql = "select " + rm.loanAccountSummarySchema() + + " where l.group_id = ? and l.client_id is null and l.loan_officer_id = ?"; - List loanAccounts = this.jdbcTemplate.query(sql, rm, new Object[] { groupId, loanOfficerId }); + final List loanAccounts = this.jdbcTemplate.query(sql, rm, new Object[] { groupId, loanOfficerId }); return loanAccounts; } @@ -540,7 +535,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { public String loanAccountSummarySchema() { - StringBuilder accountsSummary = new StringBuilder("l.id as id, l.external_id as externalId,"); + final StringBuilder accountsSummary = new StringBuilder("l.id as id, l.external_id as externalId,"); accountsSummary.append("l.product_id as productId, lp.name as productName,").append("l.loan_status_id as statusId ") .append("from m_loan l ").append("LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id "); @@ -550,11 +545,11 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { @Override public GroupAccountSummaryData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - Long id = JdbcSupport.getLong(rs, "id"); - String externalId = rs.getString("externalId"); - Long productId = JdbcSupport.getLong(rs, "productId"); - String loanProductName = rs.getString("productName"); - Integer loanStatusId = JdbcSupport.getInteger(rs, "statusId"); + final Long id = JdbcSupport.getLong(rs, "id"); + final String externalId = rs.getString("externalId"); + final Long productId = JdbcSupport.getLong(rs, "productId"); + final String loanProductName = rs.getString("productName"); + final Integer loanStatusId = JdbcSupport.getInteger(rs, "statusId"); return new GroupAccountSummaryData(id, externalId, productId, loanProductName, loanStatusId); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformService.java index 003e10173..f0d990bf4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformService.java @@ -5,25 +5,22 @@ */ package org.mifosplatform.portfolio.group.service; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; -import org.mifosplatform.portfolio.group.command.GroupCommand; import org.springframework.security.access.prepost.PreAuthorize; public interface GroupWritePlatformService { @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'CREATE_GROUP')") - CommandProcessingResult createGroup(GroupCommand command); + CommandProcessingResult createGroup(JsonCommand command); @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'UPDATE_GROUP')") - CommandProcessingResult updateGroup(GroupCommand command); + CommandProcessingResult updateGroup(Long grouptId, JsonCommand command); @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'DELETE_GROUP')") CommandProcessingResult deleteGroup(Long groupId); @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'UPDATE_GROUP')") - CommandProcessingResult assignStaff(GroupCommand command); + CommandProcessingResult unassignStaff(Long grouptId, JsonCommand command); - @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'UPDATE_GROUP')") - CommandProcessingResult unassignStaff(GroupCommand command); - } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java index d27dd75a5..9321bee97 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java @@ -6,9 +6,14 @@ package org.mifosplatform.portfolio.group.service; import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Set; +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.organisation.office.domain.Office; @@ -21,16 +26,14 @@ import org.mifosplatform.organisation.staff.exception.StaffNotFoundException; import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.domain.ClientRepository; import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; -import org.mifosplatform.portfolio.group.command.GroupCommand; -import org.mifosplatform.portfolio.group.command.GroupCommandValidator; import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.domain.GroupLevel; import org.mifosplatform.portfolio.group.domain.GroupLevelRepository; import org.mifosplatform.portfolio.group.domain.GroupRepository; -import org.mifosplatform.portfolio.group.exception.GroupLevelNotFoundException; +import org.mifosplatform.portfolio.group.exception.GroupHasNoStaffException; import org.mifosplatform.portfolio.group.exception.GroupNotFoundException; import org.mifosplatform.portfolio.group.exception.InvalidGroupLevelException; -import org.mifosplatform.portfolio.group.exception.LoanOfficerNotFoundException; +import org.mifosplatform.portfolio.group.serialization.GroupCommandFromApiJsonDeserializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,99 +48,107 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla private final static Logger logger = LoggerFactory.getLogger(GroupWritePlatformServiceJpaRepositoryImpl.class); private final PlatformSecurityContext context; - private final GroupRepository groupRepository; - private final ClientRepository clientRepository; - private final OfficeRepository officeRepository; - private final StaffRepository staffRepository; - - private final GroupLevelRepository groupLevelRepository; + private final GroupLevelRepository groupLevelRepository; + private final GroupCommandFromApiJsonDeserializer fromApiJsonDeserializer; @Autowired public GroupWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final GroupRepository groupRepository, final ClientRepository clientRepository, final OfficeRepository officeRepository, final StaffRepository staffRepository, - final GroupLevelRepository groupLevelRepository) { + final GroupLevelRepository groupLevelRepository, final GroupCommandFromApiJsonDeserializer fromApiJsonDeserializer) { this.context = context; this.groupRepository = groupRepository; this.clientRepository = clientRepository; this.officeRepository = officeRepository; this.staffRepository = staffRepository; - this.groupLevelRepository = groupLevelRepository; + this.groupLevelRepository = groupLevelRepository; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; } @Transactional @Override - public CommandProcessingResult createGroup(final GroupCommand command) { + public CommandProcessingResult createGroup(final JsonCommand command) { try { this.context.authenticatedUser(); - final GroupCommandValidator validator = new GroupCommandValidator(command); - validator.validateForCreate(); + this.fromApiJsonDeserializer.validateForCreate(command.json()); - final Office groupOffice = this.officeRepository.findOne(command.getOfficeId()); + final String name = command.stringValueOfParameterNamed("name"); + final String externalId = command.stringValueOfParameterNamed("externalId"); - if (groupOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); } + final Long parentId = command.longValueOfParameterNamed("parentId"); + + Long officeId = null; + GroupLevel groupLevel = null; + Group parentGroup = null; + + if (parentId == null) { + /* + * Scenario: Creating parent group [group with highest level] + * In-case of Centre/Groups, parent group with highest level is + * Centre. In-case of Federation/Cluster/SHG, parent group with + * highest level is Federation. In-case of + * Village/Centre/Groups, parent group with highest level is + * Village. + */ + + officeId = command.longValueOfParameterNamed("officeId"); + groupLevel = this.groupLevelRepository.findBySuperParent(true); + + } else { + + parentGroup = this.groupRepository.findOne(parentId); + if (parentGroup == null || parentGroup.isDeleted()) { throw new GroupNotFoundException(parentId); } + + officeId = parentGroup.getOfficeId(); + groupLevel = this.groupLevelRepository.findByParentId(parentGroup.getGroupLevel().getId()); + + } + + final Office groupOffice = this.officeRepository.findOne(officeId); + if (groupOffice == null) { throw new OfficeNotFoundException(officeId); } Staff staff = null; - final Long staffId = command.getStaffId(); + final Long staffId = command.longValueOfParameterNamed("staffId"); /** * Validate the staff is present in the given office or not */ if (staffId != null) { - staff = this.staffRepository.findByOffice(staffId, command.getOfficeId()); + staff = this.staffRepository.findByOffice(staffId, officeId); if (staff == null) { throw new StaffNotFoundException(staffId); } } - final Long parentId = command.getParentId(); - Group parent = null; - - /** - * Validate the parent group to check it is present. - */ - Long parentGroupLevelId = null; - if (parentId != null) { - parent = this.groupRepository.findOne(parentId); - if (parent == null) { throw new GroupNotFoundException(parentId); } - parentGroupLevelId = parent.getLevelId(); + Set clientMembers = null; + if (groupLevel.canHaveClients()) { + clientMembers = assembleSetOfClients(officeId, command); } - - final Long levelId = command.getLevelId(); - - final GroupLevel groupLevel = groupLevelRepository.findOne(levelId); - - if(groupLevel == null){throw new GroupLevelNotFoundException(levelId);} - - final Long parentLevelId = groupLevel.getParentId(); - - /* - * If Group is not super parent then validate group level's parent level is same as group parent's level - * this check makes sure new group is added at immediate next level in hierarchy - */ - if(!groupLevel.isSuperParent()){ - if (parentGroupLevelId != parentLevelId) { - final String errorMessage = "Parent group's level[" + parentLevelId + "] is not equal to child level's parent level [" - + parentGroupLevelId + "]"; - throw new InvalidGroupLevelException("add", "invalid.level", errorMessage, parentLevelId , parentGroupLevelId); - } + + Set childGroups = null; + if (groupLevel.isRecursable()) { + childGroups = assembleSetOfChildGroups(officeId, command); } - - final Set clientMembers = assembleSetOfClients(command); - final Group newGroup = Group.newGroup(groupOffice, staff, parent , levelId , command.getName(), command.getExternalId(), clientMembers); + final Group newGroup = Group + .newGroup(groupOffice, staff, parentGroup, groupLevel, name, externalId, clientMembers, childGroups); - // pre save to generate id for use in group hierarchy + // pre-save to generate id for use in group hierarchy this.groupRepository.save(newGroup); - - newGroup.generateHierarchy(); - - this.groupRepository.saveAndFlush(newGroup); - - return new CommandProcessingResult(newGroup.getId()); + newGroup.generateHierarchy(); + + this.groupRepository.saveAndFlush(newGroup); + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withOfficeId(groupOffice.getId()) // + .withGroupId(newGroup.getId()) // + .withEntityId(newGroup.getId()) // + .build(); + } catch (final DataIntegrityViolationException dve) { handleGroupDataIntegrityIssues(command, dve); return new CommandProcessingResult(Long.valueOf(-1)); @@ -146,72 +157,108 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla @Transactional @Override - public CommandProcessingResult updateGroup(final GroupCommand command) { + public CommandProcessingResult updateGroup(final Long grouptId, final JsonCommand command) { try { this.context.authenticatedUser(); - final GroupCommandValidator validator = new GroupCommandValidator(command); - validator.validateForUpdate(); + final Map actualChanges = new LinkedHashMap(9); - final Group groupForUpdate = this.groupRepository.findOne(command.getId()); - if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(command.getId()); } + this.fromApiJsonDeserializer.validateForUpdate(command.json()); - Office groupOffice = null; - final Long officeId = command.getOfficeId(); - Staff staff = null; - final Long staffId = command.getStaffId(); + final Group groupForUpdate = this.groupRepository.findOne(grouptId); + if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(grouptId); } - if (command.isOfficeIdChanged() && command.isStaffChanged()) { - /** - * Scenario: Both Office and Staff are changed, check new - * staff is present in new office - */ - if (officeId != null) { - groupOffice = this.officeRepository.findOne(officeId); - if (groupOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); } - } - if (staffId != null) { - staff = this.staffRepository.findByOffice(staffId, officeId); - if (staff == null) { throw new LoanOfficerNotFoundException(staffId); } - } + final Long officeId = groupForUpdate.getOfficeId(); - } else if (command.isOfficeIdChanged()) { - /** - * Scenario: Only Office is changed, check new office has - * present staff, This situation is not practical as - * staff can't be present in two offices - */ - // TODO When office is changed need to make sure all the staff - // at loan level are also updated or verified - - if (officeId != null) { - groupOffice = this.officeRepository.findOne(officeId); - if (groupOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); } - } - if (staffId != null) { - staff = this.staffRepository.findByOffice(staffId, groupForUpdate.getOfficeId()); - if (staff == null) { throw new LoanOfficerNotFoundException(staffId); } - } + final String nameParamName = "name"; + if (command.isChangeInStringParameterNamed(nameParamName, groupForUpdate.getName())) { + final String newValue = command.stringValueOfParameterNamed(nameParamName); + actualChanges.put(nameParamName, newValue); + groupForUpdate.setName(StringUtils.defaultIfEmpty(newValue, null)); + } - } else if (command.isStaffChanged()) { - /** - * Scenario: Only staff is changed, check new new loan - * officer is in present assigned office - */ - if (staffId != null) { - staff = this.staffRepository.findByOffice(staffId, groupForUpdate.getOfficeId()); - if (staff == null) { throw new LoanOfficerNotFoundException(staffId); } + final String externalIdParamName = "externalId"; + if (command.isChangeInStringParameterNamed(externalIdParamName, groupForUpdate.getExternalId())) { + final String newValue = command.stringValueOfParameterNamed(externalIdParamName); + actualChanges.put(externalIdParamName, newValue); + groupForUpdate.setExternalId(StringUtils.defaultIfEmpty(newValue, null)); + } + + final Staff presentStaff = groupForUpdate.getStaff(); + Long presentStaffId = null; + if (presentStaff != null) { + presentStaffId = presentStaff.getId(); + } + + final String staffIdParamName = "staffId"; + if (command.isChangeInLongParameterNamed(staffIdParamName, presentStaffId)) { + final Long newValue = command.longValueOfParameterNamed(staffIdParamName); + actualChanges.put(staffIdParamName, newValue); + final Staff newStaff = this.staffRepository.findByOffice(newValue, officeId); + if (newStaff == null) { throw new StaffNotFoundException(newValue); } + groupForUpdate.setStaff(newStaff); + } + + final GroupLevel groupLevel = this.groupLevelRepository.findOne(groupForUpdate.getGroupLevel().getId()); + + /* + * Ignoring parentId param, if group for update is super parent. + * TODO Need to check: Ignoring is correct or need throw unsupported + * param + */ + if (!groupLevel.isSuperParent()) { + final String parentIdParamName = "parentId"; + final Long parentId = groupForUpdate.getParent().getId(); + if (command.isChangeInLongParameterNamed(parentIdParamName, parentId)) { + + final Long newValue = command.longValueOfParameterNamed(parentIdParamName); + actualChanges.put(parentIdParamName, newValue); + final Group newParentGroup = this.groupRepository.findOne(newValue); + + if (newParentGroup == null || newParentGroup.isDeleted()) { throw new StaffNotFoundException(newValue); } + + if (!newParentGroup.isOfficeIdentifiedBy(officeId)) { + final String errorMessage = "Group and parent group must have the same office"; + throw new InvalidOfficeException("group", "attach.to.parent.group", errorMessage); + } + + /* + * If Group is not super parent then validate group level's + * parent level is same as group parent's level this check + * makes sure new group is added at immediate next level in + * hierarchy + */ + + if (!groupForUpdate.getGroupLevel().isIdentifiedByParentId(newParentGroup.getGroupLevel().getId())) { + final String errorMessage = "Parent group's level is not equal to child level's parent level "; + throw new InvalidGroupLevelException("add", "invalid.level", errorMessage); + } + + groupForUpdate.setParent(newParentGroup); } } - final Set clientMembers = assembleSetOfClients(command); + final Set clientMembers = assembleSetOfClients(officeId, command); + final String clientMembersParamName = "clientMembers"; - groupForUpdate.update(command, groupOffice, staff, clientMembers); + if (!clientMembers.equals(groupForUpdate.getClientMembers())) { + final String[] newValue = command.arrayValueOfParameterNamed(clientMembersParamName); + // TODO Use Guava's symmetricDifference + actualChanges.put(clientMembersParamName, newValue); + groupForUpdate.setClientMembers(clientMembers); + } this.groupRepository.saveAndFlush(groupForUpdate); - return new CommandProcessingResult(groupForUpdate.getId()); + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withOfficeId(groupForUpdate.getId()) // + .withGroupId(groupForUpdate.getOfficeId()) // + .withEntityId(groupForUpdate.getId()) // + .with(actualChanges) // + .build(); + } catch (final DataIntegrityViolationException dve) { handleGroupDataIntegrityIssues(command, dve); return new CommandProcessingResult(Long.valueOf(-1)); @@ -220,55 +267,37 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla @Transactional @Override - - public CommandProcessingResult assignStaff(final GroupCommand command) { + public CommandProcessingResult unassignStaff(final Long grouptId, final JsonCommand command) { this.context.authenticatedUser(); - final GroupCommandValidator validator = new GroupCommandValidator(command); - validator.validateForStaffUpdate(); + final Map actualChanges = new LinkedHashMap(9); - final Group groupForUpdate = this.groupRepository.findOne(command.getId()); - if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(command.getId()); } + this.fromApiJsonDeserializer.validateForUnassignStaff(command.json()); - Staff staff = null; - final Long staffId = command.getStaffId(); - if (command.isStaffChanged() && staffId != null) { - staff = this.staffRepository.findByOffice(staffId, groupForUpdate.getOfficeId()); - if (staff == null) { throw new LoanOfficerNotFoundException(staffId); } + final Group groupForUpdate = this.groupRepository.findOne(grouptId); + if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(grouptId); } + + final Staff presentStaff = groupForUpdate.getStaff(); + Long presentStaffId = null; + if (presentStaff == null) { throw new GroupHasNoStaffException(grouptId); } + presentStaffId = presentStaff.getId(); + final String staffIdParamName = "staffId"; + if (!command.isChangeInLongParameterNamed(staffIdParamName, presentStaffId)) { + groupForUpdate.unassigStaff(); } - - groupForUpdate.assigStaff(command, staff); - this.groupRepository.saveAndFlush(groupForUpdate); - return new CommandProcessingResult(groupForUpdate.getId()); - } + actualChanges.put(staffIdParamName, null); - @Transactional - @Override - public CommandProcessingResult unassignStaff(final GroupCommand command) { + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withOfficeId(groupForUpdate.getId()) // + .withGroupId(groupForUpdate.getOfficeId()) // + .withEntityId(groupForUpdate.getId()) // + .with(actualChanges) // + .build(); - this.context.authenticatedUser(); - - final GroupCommandValidator validator = new GroupCommandValidator(command); - validator.validateForStaffUpdate(); - - final Group groupForUpdate = this.groupRepository.findOne(command.getId()); - if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(command.getId()); } - - final Long staffId = command.getStaffId(); - final Long presentStaffId = groupForUpdate.getStaffId(); - - if (command.isStaffChanged() && staffId != null) { - if (!staffId.equals(presentStaffId)) { throw new LoanOfficerNotFoundException(staffId); } - } - - groupForUpdate.unassigStaff(command); - - this.groupRepository.saveAndFlush(groupForUpdate); - - return new CommandProcessingResult(groupForUpdate.getId()); } @Transactional @@ -277,25 +306,31 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla this.context.authenticatedUser(); + // TODO add logic to check any active group loans are preset + final Group groupForDelete = this.groupRepository.findOne(groupId); if (groupForDelete == null || groupForDelete.isDeleted()) { throw new GroupNotFoundException(groupId); } groupForDelete.delete(); this.groupRepository.save(groupForDelete); - return new CommandProcessingResult(groupId); + return new CommandProcessingResultBuilder() // + .withOfficeId(groupForDelete.getId()) // + .withGroupId(groupForDelete.getOfficeId()) // + .withEntityId(groupForDelete.getId()) // + .build(); } - private Set assembleSetOfClients(final GroupCommand command) { + private Set assembleSetOfClients(final Long officeId, final JsonCommand command) { final Set clientMembers = new HashSet(); - final String[] clientMembersArray = command.getClientMembers(); + final String[] clientMembersArray = command.arrayValueOfParameterNamed("clientMembers"); - if (command.isClientMembersChanged() && !ObjectUtils.isEmpty(clientMembersArray)) { + if (!ObjectUtils.isEmpty(clientMembersArray)) { for (final String clientId : clientMembersArray) { final Long id = Long.valueOf(clientId); final Client client = this.clientRepository.findOne(id); if (client == null || client.isDeleted()) { throw new ClientNotFoundException(id); } - if (!client.isOfficeIdentifiedBy(command.getOfficeId())) { + if (!client.isOfficeIdentifiedBy(officeId)) { final String errorMessage = "Group and Client must have the same office."; throw new InvalidOfficeException("client", "attach.to.group", errorMessage); } @@ -306,18 +341,39 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla return clientMembers; } + private Set assembleSetOfChildGroups(final Long officeId, final JsonCommand command) { + + final Set childGroups = new HashSet(); + final String[] childGroupsArray = command.arrayValueOfParameterNamed("childGroups"); + + if (!ObjectUtils.isEmpty(childGroupsArray)) { + for (final String groupId : childGroupsArray) { + final Long id = Long.valueOf(groupId); + final Group group = this.groupRepository.findOne(id); + if (group == null || group.isDeleted()) { throw new GroupNotFoundException(id); } + if (!group.isOfficeIdentifiedBy(officeId)) { + final String errorMessage = "Group and child groups must have the same office."; + throw new InvalidOfficeException("group", "attach.to.parent.group", errorMessage); + } + childGroups.add(group); + } + } + + return childGroups; + } + /* * Guaranteed to throw an exception no matter what the data integrity issue * is. */ - private void handleGroupDataIntegrityIssues(final GroupCommand command, final DataIntegrityViolationException dve) { + private void handleGroupDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { final Throwable realCause = dve.getMostSpecificCause(); if (realCause.getMessage().contains("external_id")) { throw new PlatformDataIntegrityException("error.msg.group.duplicate.externalId", "Group with externalId {0} already exists", - "externalId", command.getExternalId()); + "externalId", command.stringValueOfParameterNamed("externalId")); } else if (realCause.getMessage().contains("name")) { throw new PlatformDataIntegrityException("error.msg.group.duplicate.name", - "Group with name {0} already exists", "name", command.getName()); } + "Group with name {0} already exists", "name", command.stringValueOfParameterNamed("name")); } logger.error(dve.getMessage(), dve); throw new PlatformDataIntegrityException("error.msg.group.unknown.data.integrity.issue",