diff --git a/mifosng-db/patches/patch-0008-add_office_to_group.sql b/mifosng-db/patches/patch-0008-add_office_to_group.sql new file mode 100644 index 000000000..9899e2d2f --- /dev/null +++ b/mifosng-db/patches/patch-0008-add_office_to_group.sql @@ -0,0 +1,3 @@ +alter table m_group add column office_id bigint(20) NOT NULL AFTER id; +update m_group set office_id = 1 WHERE office_id = 0; +alter table m_group add constraint foreign key (`office_id`) references `m_office` (`id`); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/GroupsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/GroupsApiResource.java index a6d1c743c..db3e5b0f2 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/GroupsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/GroupsApiResource.java @@ -1,5 +1,6 @@ package org.mifosng.platform.api; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -22,12 +23,14 @@ import org.mifosng.platform.api.commands.GroupCommand; import org.mifosng.platform.api.data.ClientLookup; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.GroupData; +import org.mifosng.platform.api.data.OfficeLookup; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; import org.mifosng.platform.api.infrastructure.ApiParameterHelper; import org.mifosng.platform.client.service.ClientReadPlatformService; import org.mifosng.platform.group.service.GroupReadPlatformService; import org.mifosng.platform.group.service.GroupWritePlatformService; +import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -48,19 +51,22 @@ public class GroupsApiResource { @Autowired private ApiDataConversionService apiDataConversionService; - + + @Autowired + private OfficeReadPlatformService officeReadPlatformService; + @Autowired private ApiJsonSerializerService apiJsonSerializerService; - + + private static final Set typicalResponseParameters = new HashSet( + Arrays.asList("id", "officeId", "name", "externalId", "clientMembers") + ); + @GET @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) public String retrieveAllGroups(@Context final UriInfo uriInfo){ - - Set typicalResponseParameters = new HashSet( - Arrays.asList("id", "name", "externalId") - ); - + Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { responseParameters.addAll(typicalResponseParameters); @@ -79,8 +85,6 @@ public class GroupsApiResource { @Produces({ MediaType.APPLICATION_JSON }) public String retrieveGroupData(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) { - Set typicalResponseParameters = new HashSet(Arrays.asList("id", "name", "externalId", "clientMembers")); - Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo .getQueryParameters()); if (responseParameters.isEmpty()) { @@ -101,6 +105,9 @@ public class GroupsApiResource { group.setAllowedClients(availableClients); responseParameters.add("allowedClients"); + + group.setAllowedOffices(new ArrayList(officeReadPlatformService.retrieveAllOfficesForLookup())); + responseParameters.add("allowedOffices"); } return this.apiJsonSerializerService.serializeGroupDataToJson(prettyPrint, responseParameters, group); @@ -112,14 +119,14 @@ public class GroupsApiResource { @Produces({MediaType.APPLICATION_JSON}) public String newGroupDetails(@Context final UriInfo uriInfo) { - Set typicalResponseParameters = new HashSet(Arrays.asList("id", "name", "externalId", "allowedClients")); - Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { responseParameters.addAll(typicalResponseParameters); } boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + responseParameters.addAll(Arrays.asList("allowedClients", "allowedOffices")); + GroupData groupData = this.groupReadPlatformService.retrieveNewGroupDetails(); return this.apiJsonSerializerService.serializeGroupDataToJson(prettyPrint, responseParameters, groupData); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/GroupCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/GroupCommand.java index 4ece7412e..9527121c7 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/GroupCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/GroupCommand.java @@ -7,18 +7,26 @@ public class GroupCommand { private final Long id; private final String externalId; private final String name; + private final Long officeId; + private final String[] clientMembers; private final Set modifiedParameters; - public GroupCommand(Set modifiedParameters, final Long id, String externalId, String name, String[] clientMembers) { + public GroupCommand(Set modifiedParameters, final Long id, final String externalId, final String name, + final Long officeId, String[] clientMembers) { this.id = id; + this.officeId = officeId; this.externalId = externalId; this.name = name; this.clientMembers = clientMembers; this.modifiedParameters = modifiedParameters; } + public Long getOfficeId() { + return officeId; + } + public String getExternalId() { return externalId; } @@ -35,6 +43,10 @@ public class GroupCommand { return clientMembers; } + public boolean isOfficeIdChanged() { + return this.modifiedParameters.contains("officeId"); + } + public boolean isNameChanged() { return this.modifiedParameters.contains("name"); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/GroupData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/GroupData.java index 1d531be6b..c4ed19e55 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/GroupData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/GroupData.java @@ -2,27 +2,36 @@ package org.mifosng.platform.api.data; import java.util.ArrayList; import java.util.Collection; +import java.util.List; public class GroupData { private final Long id; private final String name; private final String externalId; - + private final Long officeId; + private final String officeName; + private Collection clientMembers = new ArrayList(); private Collection allowedClients = new ArrayList(); - - public GroupData(Long id, String name, String externalId) { + private Collection allowedOffices = new ArrayList(); + + public GroupData(Long id, Long officeId, String officeName, String name, String externalId) { this.id = id; this.name = name; this.externalId = externalId; + this.officeId = officeId; + this.officeName = officeName; } - public GroupData(Collection allowedClients) { + public GroupData(Collection allowedClients, Collection allowedOffices){ this.id = null; this.name = null; this.externalId = null; + this.officeId = null; + this.officeName = null; this.allowedClients = allowedClients; + this.allowedOffices = allowedOffices; } public Long getId() { @@ -52,4 +61,12 @@ public class GroupData { public void setAllowedClients(Collection allowedClients) { this.allowedClients = allowedClients; } + + public Collection getAllowedOffices() { + return allowedOffices; + } + + public void setAllowedOffices(Collection allowedOffices) { + this.allowedOffices = allowedOffices; + } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index c469711bc..ededf508b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -338,13 +338,14 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Map requestMap = gsonConverter.fromJson(json, typeOfMap); Set supportedParams = new HashSet( - Arrays.asList("name", "externalId", "clientMembers") + Arrays.asList("name", "officeId", "externalId", "clientMembers") ); checkForUnsupportedParameters(requestMap, supportedParams); Set modifiedParameters = new HashSet(); - + + Long officeId = extractLongParameter("officeId", requestMap, modifiedParameters); String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); String name = extractStringParameter("name", requestMap, modifiedParameters); @@ -366,7 +367,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } // - return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name, clientMembers); + return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name, officeId, clientMembers); } @Override diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java index 5cdbd2c5b..1671a945f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java @@ -132,8 +132,8 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ "preclosedDepositAccountsCount","preclosedDepositAccounts")); private static final Set GROUP_DATA_PARAMETERS = new HashSet( - Arrays.asList("id", "name", "externalId", "clientMembers", - "allowedClients")); + Arrays.asList("id", "officeId", "name", "externalId", "clientMembers", + "allowedClients", "allowedOffices")); private static final Set NOTE_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "clientId", "loanId", "loanTransactionId", diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/group/domain/Group.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/domain/Group.java index 146f2647e..a5d390e0e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/group/domain/Group.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/group/domain/Group.java @@ -8,18 +8,24 @@ import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; import javax.persistence.Table; import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.GroupCommand; import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; +import org.mifosng.platform.organisation.domain.Office; import org.mifosng.platform.user.domain.AppUser; @Entity @Table(name = "m_group") public class Group extends AbstractAuditableCustom { + @ManyToOne + @JoinColumn(name = "office_id", nullable = false) + private Office office; + @Column(name = "name", length = 100, unique = true) private String name; @@ -41,11 +47,12 @@ public class Group extends AbstractAuditableCustom { this.clientMembers = new HashSet(); } - public static Group newGroup(String name, String externalId, Set clientMembers){ - return new Group(name, externalId, clientMembers); + public static Group newGroup(Office office, String name, String externalId, Set clientMembers){ + return new Group(office, name, externalId, clientMembers); } - public Group(String name, String externalId, Set clientMembers) { + public Group(Office office, String name, String externalId, Set clientMembers) { + this.office = office; if (StringUtils.isNotBlank(name)) { this.name = name.trim(); } else { @@ -61,11 +68,15 @@ public class Group extends AbstractAuditableCustom { } } - public void update(final GroupCommand command, final Set clientMembers) { + public void update(final GroupCommand command, final Office groupOffice, final Set clientMembers) { if (command.isExternalIdChanged()) { this.externalId = command.getExternalId(); } + if (command.isOfficeIdChanged()) { + this.office = groupOffice; + } + if (command.isNameChanged()) { this.name = command.getName(); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupCommandValidator.java index 1ef5fa539..b92c361c2 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupCommandValidator.java @@ -26,7 +26,9 @@ public class GroupCommandValidator { baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); baseDataValidator.reset().parameter("clientMembers").value(command.getClientMembers()).arrayNotEmpty(); - + + baseDataValidator.reset().parameter("officeId").value(command.getOfficeId()).notNull().integerGreaterThanZero(); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } @@ -43,7 +45,11 @@ public class GroupCommandValidator { baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); baseDataValidator.reset().parameter("clientMembers").value(command.getClientMembers()).arrayNotEmpty(); - + + 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); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java index e1fe1d99c..c6600f119 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java @@ -9,9 +9,11 @@ import java.util.List; import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.data.ClientLookup; import org.mifosng.platform.api.data.GroupData; +import org.mifosng.platform.api.data.OfficeLookup; import org.mifosng.platform.client.service.ClientReadPlatformService; import org.mifosng.platform.exceptions.GroupNotFoundException; import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; +import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.mifosng.platform.security.PlatformSecurityContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; @@ -25,13 +27,16 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { private final JdbcTemplate jdbcTemplate; private final PlatformSecurityContext context; private final ClientReadPlatformService clientReadPlatformService; + private final OfficeReadPlatformService officeReadPlatformService; @Autowired public GroupReadPlatformServiceImpl(final PlatformSecurityContext context, - final TenantAwareRoutingDataSource dataSource, ClientReadPlatformService clientReadPlatformService) { + final TenantAwareRoutingDataSource dataSource, ClientReadPlatformService clientReadPlatformService, + final OfficeReadPlatformService officeReadPlatformService) { this.context = context; this.jdbcTemplate = new JdbcTemplate(dataSource); this.clientReadPlatformService = clientReadPlatformService; + this.officeReadPlatformService = officeReadPlatformService; } @Override @@ -70,13 +75,16 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { List allowedClients = new ArrayList( this.clientReadPlatformService.retrieveAllIndividualClientsForLookup()); - return new GroupData(allowedClients); + List allowedOffices = new ArrayList(officeReadPlatformService.retrieveAllOfficesForLookup()); + + return new GroupData(allowedClients, allowedOffices); } private static final class GroupMapper implements RowMapper { public String groupSchema() { - return "g.id as id, g.external_id as externalId, g.name as name from m_group g"; + return "g.office_id as officeId, o.name as officeName, g.id as id, g.external_id as externalId, " + + "g.name as name from m_group g join m_office o on o.id = g.office_id"; } @Override @@ -86,7 +94,10 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { String name = rs.getString("name"); String externalId = rs.getString("externalId"); - return new GroupData(id, name, externalId); + Long officeId = rs.getLong("officeId"); + String officeName = rs.getString("officeName"); + + return new GroupData(id, officeId, officeName, name, externalId); } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java index 55aa5a271..6453185f6 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java @@ -9,9 +9,12 @@ import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.client.domain.ClientRepository; import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.GroupNotFoundException; +import org.mifosng.platform.exceptions.OfficeNotFoundException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException; import org.mifosng.platform.group.domain.Group; import org.mifosng.platform.group.domain.GroupRepository; +import org.mifosng.platform.organisation.domain.Office; +import org.mifosng.platform.organisation.domain.OfficeRepository; import org.mifosng.platform.security.PlatformSecurityContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,12 +35,15 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla private final ClientRepository clientRepository; + private final OfficeRepository officeRepository; + @Autowired public GroupWritePlatformServiceJpaRepositoryImpl(PlatformSecurityContext context, GroupRepository groupRepository, - ClientRepository clientRepository) { + ClientRepository clientRepository, OfficeRepository officeRepository) { this.context = context; this.groupRepository = groupRepository; this.clientRepository = clientRepository; + this.officeRepository = officeRepository; } @Transactional @@ -49,9 +55,14 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla GroupCommandValidator validator = new GroupCommandValidator(command); validator.validateForCreate(); + Office groupOffice = this.officeRepository.findOne(command.getOfficeId()); + if (groupOffice == null) { + throw new OfficeNotFoundException(command.getOfficeId()); + } + final Set clientMembers = assembleSetOfClients(command); - Group newGroup = Group.newGroup(command.getName(), command.getExternalId(), clientMembers); + Group newGroup = Group.newGroup(groupOffice, command.getName(), command.getExternalId(), clientMembers); this.groupRepository.saveAndFlush(newGroup); @@ -77,9 +88,18 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla throw new GroupNotFoundException(command.getId()); } + Office groupOffice = null; + Long officeId = command.getOfficeId(); + if (command.isOfficeIdChanged() && officeId != null) { + groupOffice = this.officeRepository.findOne(officeId); + if (groupOffice == null) { + throw new OfficeNotFoundException(command.getOfficeId()); + } + } + final Set clientMembers = assembleSetOfClients(command); - groupForUpdate.update(command, clientMembers); + groupForUpdate.update(command, groupOffice, clientMembers); groupRepository.saveAndFlush(groupForUpdate);