diff --git a/mifosng-db/patches/patch-0005_Add_join_table_for_client_and_group.sql b/mifosng-db/patches/patch-0005_Add_join_table_for_client_and_group.sql new file mode 100644 index 000000000..ab5ca0996 --- /dev/null +++ b/mifosng-db/patches/patch-0005_Add_join_table_for_client_and_group.sql @@ -0,0 +1,8 @@ +CREATE TABLE `portfolio_group_client` ( + `group_id` bigint(20) NOT NULL, + `client_id` bigint(20) NOT NULL, + PRIMARY KEY (`group_id`,`client_id`), + FOREIGN KEY (`group_id`) REFERENCES `portfolio_group` (`id`), + FOREIGN KEY (`client_id`) REFERENCES `portfolio_client` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + 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 10f0ee383..4ece7412e 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,13 +7,15 @@ public class GroupCommand { private final Long id; private final String externalId; private final String name; + private final String[] clientMembers; private final Set modifiedParameters; - public GroupCommand(Set modifiedParameters, final Long id, String externalId, String name) { + public GroupCommand(Set modifiedParameters, final Long id, String externalId, String name, String[] clientMembers) { this.id = id; this.externalId = externalId; this.name = name; + this.clientMembers = clientMembers; this.modifiedParameters = modifiedParameters; } @@ -29,6 +31,10 @@ public class GroupCommand { return id; } + public String[] getClientMembers() { + return clientMembers; + } + public boolean isNameChanged() { return this.modifiedParameters.contains("name"); } @@ -37,4 +43,8 @@ public class GroupCommand { return this.modifiedParameters.contains("externalId"); } + public boolean isClientMembersChanged() { + return this.modifiedParameters.contains("clientMembers"); + } + } 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 e166ab0fb..bae6f2978 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 @@ -859,11 +859,11 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { throw new InvalidJsonException(); } - Type typeOfMap = new TypeToken>(){}.getType(); + Type typeOfMap = new TypeToken>(){}.getType(); Map requestMap = gsonConverter.fromJson(json, typeOfMap); Set supportedParams = new HashSet( - Arrays.asList("name", "externalId") + Arrays.asList("name", "externalId", "clientMembers") ); checkForUnsupportedParameters(requestMap, supportedParams); @@ -873,7 +873,25 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); String name = extractStringParameter("name", requestMap, modifiedParameters); - return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name); + // check array + 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 { - @SuppressWarnings("unused") @Column(name = "name", length = 100) private String name; @@ -23,16 +29,23 @@ public class Group extends AbstractAuditableCustom { @Column(name = "is_deleted", nullable=false) private boolean deleted = false; + @ManyToMany + @JoinTable(name = "portfolio_group_client", + joinColumns = @JoinColumn(name = "group_id"), + inverseJoinColumns = @JoinColumn(name = "client_id")) + private Set clientMembers; + public Group() { this.name = null; this.externalId = null; + this.clientMembers = new HashSet(); } - public static Group newGroup(String name, String externalId){ - return new Group(name, externalId); + public static Group newGroup(String name, String externalId, Set clientMembers){ + return new Group(name, externalId, clientMembers); } - public Group(String name, String externalId) { + public Group(String name, String externalId, Set clientMembers) { if (StringUtils.isNotBlank(name)) { this.name = name.trim(); } else { @@ -43,6 +56,9 @@ public class Group extends AbstractAuditableCustom { } else { this.externalId = null; } + if (clientMembers != null){ + this.clientMembers = clientMembers; + } } public void update(GroupCommand command) { @@ -55,6 +71,10 @@ public class Group extends AbstractAuditableCustom { } } + public void addClientMember(final Client member){ + this.clientMembers.add(member); + } + /** * Delete is a soft delete. Updates flag on group so it wont appear in query/report results. * 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 96f9c531b..57f2ec2a2 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 @@ -25,6 +25,8 @@ public class GroupCommandValidator { baseDataValidator.reset().parameter("name").value(command.getName()).notBlank(); baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); + baseDataValidator.reset().parameter("clientMembers").value(command.getClientMembers()).ignoreIfNull().arrayNotEmpty(); + 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/GroupWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupWritePlatformServiceJpaRepositoryImpl.java index 5ff7eb08b..737592b07 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 @@ -1,7 +1,13 @@ package org.mifosng.platform.group.service; +import java.util.HashSet; +import java.util.Set; + import org.mifosng.platform.api.commands.GroupCommand; import org.mifosng.platform.api.data.EntityIdentifier; +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.group.domain.Group; import org.mifosng.platform.group.domain.GroupRepository; @@ -9,70 +15,96 @@ import org.mifosng.platform.security.PlatformSecurityContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; @Service public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePlatformService { private final PlatformSecurityContext context; - + private final GroupRepository groupRepository; - + + private final ClientRepository clientRepository; + @Autowired - public GroupWritePlatformServiceJpaRepositoryImpl(PlatformSecurityContext context, GroupRepository groupRepository) { + public GroupWritePlatformServiceJpaRepositoryImpl(PlatformSecurityContext context, GroupRepository groupRepository, + ClientRepository clientRepository) { this.context = context; this.groupRepository = groupRepository; + this.clientRepository = clientRepository; } @Transactional @Override public EntityIdentifier createGroup(GroupCommand command) { - + this.context.authenticatedUser(); - + GroupCommandValidator validator = new GroupCommandValidator(command); validator.validateForCreate(); - - Group newGroup = Group.newGroup(command.getName(), command.getExternalId()); - + + final Set clientMembers = assembleSetOfClients(command); + + Group newGroup = Group.newGroup(command.getName(), command.getExternalId(), clientMembers); + this.groupRepository.save(newGroup); - + return new EntityIdentifier(newGroup.getId()); } @Transactional @Override public EntityIdentifier updateGroup(GroupCommand command) { - + context.authenticatedUser(); - + GroupCommandValidator validator = new GroupCommandValidator(command); validator.validateForUpdate(); - + Group groupForUpdate = this.groupRepository.findOne(command.getId()); - if (groupForUpdate == null || groupForUpdate.isDeleted()){ + if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(command.getId()); } groupForUpdate.update(command); - + groupRepository.save(groupForUpdate); - + return new EntityIdentifier(groupForUpdate.getId()); } @Transactional @Override public EntityIdentifier deleteGroup(Long groupId) { - + context.authenticatedUser(); - + Group groupForDelete = this.groupRepository.findOne(groupId); - if (groupForDelete == null || groupForDelete.isDeleted()){ + if (groupForDelete == null || groupForDelete.isDeleted()) { throw new GroupNotFoundException(groupId); } groupForDelete.delete(); this.groupRepository.save(groupForDelete); - + return new EntityIdentifier(groupId); } + private Set assembleSetOfClients(final GroupCommand command) { + + Set clientMembers = new HashSet(); + String[] clientMembersArray = command.getClientMembers(); + + if (command.isClientMembersChanged() && !ObjectUtils.isEmpty(clientMembersArray)) { + for (String clientId : clientMembersArray) { + Long id = Long.valueOf(clientId); + Client client = this.clientRepository.findOne(id); + if (client == null) { + throw new ClientNotFoundException(id); + } + clientMembers.add(client); + } + } + + return clientMembers; + } + }