Added assign/unassign loanofficerto group and update api docs

This commit is contained in:
Nayan Ambali
2013-02-16 18:28:03 +05:30
parent 16ae622590
commit 8e02d51b14
9 changed files with 625 additions and 69 deletions
@@ -24,6 +24,7 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name") })
public class Staff extends AbstractPersistable<Long> {
@Column(name = "firstname", length = 50)
private String firstname;
@@ -7,8 +7,20 @@ package org.mifosplatform.organisation.staff.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface StaffRepository extends JpaRepository<Staff, Long>,
JpaSpecificationExecutor<Staff> {
// no added behaviour
public final static String FIND_BY_OFFICE_QUERY = "select s from Staff s where s.id = :id AND s.office.id = :officeId";
/**
* Find staff by officeid.
*/
@Query(FIND_BY_OFFICE_QUERY)
public Staff findByOffice(@Param("id") Long id, @Param("officeId") Long officeId);
}
@@ -24,9 +24,12 @@ 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.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
@@ -165,6 +168,32 @@ public class GroupsApiResource {
return this.toApiJsonSerializer.serialize(entityIdentifier);
}
@POST
@Path("{groupId}/command/assign_loanofficer")
@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.assignLoanOfficer(command);
return this.toApiJsonSerializer.serialize(entityIdentifier);
}
@POST
@Path("{groupId}/command/unassign_loanofficer")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String unassignLoanOfficer(@PathParam("groupId") final Long groupId, final String jsonRequestBody) {
final GroupCommand command = this.apiDataConversionService.convertJsonToGroupCommand(groupId, jsonRequestBody);
CommandProcessingResult entityIdentifier = this.groupWritePlatformService.unassignLoanOfficer(command);
return this.toApiJsonSerializer.serialize(entityIdentifier);
}
@PUT
@Path("{groupId}")
@@ -243,4 +272,8 @@ public class GroupsApiResource {
return extraCriteria;
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
}
@@ -59,4 +59,21 @@ public class GroupCommandValidator {
}
}
public void validateForLoanOfficerUpdate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("group");
baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
if (command.isLoanOfficerChanged()) {
baseDataValidator.reset().parameter("loanOfficerId").value(command.getLoanOfficeId()).notNull().integerGreaterThanZero();
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -34,7 +34,7 @@ public class Group extends AbstractPersistable<Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "loan_officer_id", nullable = false)
@JoinColumn(name = "loan_officer_id", nullable = true)
private Staff loanOfficer;
@Column(name = "name", length = 100, unique = true)
@@ -78,6 +78,14 @@ public class Group extends AbstractPersistable<Long> {
}
}
public Long getOfficeId() {
return this.office.getId();
}
public Long getLoanOfficerId() {
return this.loanOfficer.getId();
}
public void update(final GroupCommand command, final Office groupOffice, final Staff newLoanOfficer, final Set<Client> clientMembers) {
if (command.isExternalIdChanged()) {
this.externalId = command.getExternalId();
@@ -100,6 +108,18 @@ public class Group extends AbstractPersistable<Long> {
}
}
public void assigLoanOfficer(final GroupCommand command , final Staff newLoanOfficer){
if (command.isLoanOfficerChanged()) {
this.loanOfficer = newLoanOfficer;
}
}
public void unassigLoanOfficer(GroupCommand command) {
if (command.isLoanOfficerChanged()) {
this.loanOfficer = null;
}
}
public void addClientMember(final Client member) {
this.clientMembers.add(member);
}
@@ -123,4 +143,5 @@ public class Group extends AbstractPersistable<Long> {
public boolean isDeleted() {
return deleted;
}
}
@@ -19,5 +19,11 @@ public interface GroupWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'DELETE_GROUP')")
CommandProcessingResult deleteGroup(Long groupId);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'UPDATE_GROUP')")
CommandProcessingResult assignLoanOfficer(GroupCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'UPDATE_GROUP')")
CommandProcessingResult unassignLoanOfficer(GroupCommand command);
}
@@ -52,12 +52,12 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
@Autowired
public GroupWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final GroupRepository groupRepository,
final ClientRepository clientRepository, final OfficeRepository officeRepository , final StaffRepository staffRepository) {
final ClientRepository clientRepository, final OfficeRepository officeRepository, final StaffRepository staffRepository) {
this.context = context;
this.groupRepository = groupRepository;
this.clientRepository = clientRepository;
this.officeRepository = officeRepository;
this.staffRepository = staffRepository;
this.staffRepository = staffRepository;
}
@Transactional
@@ -66,35 +66,29 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
try {
this.context.authenticatedUser();
GroupCommandValidator validator = new GroupCommandValidator(command);
final GroupCommandValidator validator = new GroupCommandValidator(command);
validator.validateForCreate();
Office groupOffice = this.officeRepository.findOne(command.getOfficeId());
final Office groupOffice = this.officeRepository.findOne(command.getOfficeId());
Staff loanOfficer = null;
Long loanOfficerId = command.getLoanOfficeId();
final Long loanOfficerId = command.getLoanOfficeId();
if (groupOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); }
if (loanOfficerId != null) {
// TODO Set the scope for staffRepository.findOneByOfficeId to a officer equal to groupOffice
loanOfficer = this.staffRepository.findOne(loanOfficerId);
if (loanOfficer == null) {
throw new StaffNotFoundException(loanOfficerId);
}
}
if (groupOffice == null) {
throw new OfficeNotFoundException(command.getOfficeId());
loanOfficer = this.staffRepository.findByOffice(loanOfficerId, command.getOfficeId());
if (loanOfficer == null) { throw new StaffNotFoundException(loanOfficerId); }
}
final Set<Client> clientMembers = assembleSetOfClients(command);
Group newGroup = Group.newGroup(groupOffice, loanOfficer , command.getName(), command.getExternalId(), clientMembers);
final Group newGroup = Group.newGroup(groupOffice, loanOfficer, command.getName(), command.getExternalId(), clientMembers);
this.groupRepository.saveAndFlush(newGroup);
return new CommandProcessingResult(newGroup.getId());
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleGroupDataIntegrityIssues(command, dve);
return new CommandProcessingResult(Long.valueOf(-1));
}
@@ -105,58 +99,136 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
public CommandProcessingResult updateGroup(final GroupCommand command) {
try {
context.authenticatedUser();
this.context.authenticatedUser();
GroupCommandValidator validator = new GroupCommandValidator(command);
final GroupCommandValidator validator = new GroupCommandValidator(command);
validator.validateForUpdate();
Group groupForUpdate = this.groupRepository.findOne(command.getId());
if (groupForUpdate == null || groupForUpdate.isDeleted()) {
throw new GroupNotFoundException(command.getId());
}
final Group groupForUpdate = this.groupRepository.findOne(command.getId());
if (groupForUpdate == null || groupForUpdate.isDeleted()) { 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 Long officeId = command.getOfficeId();
Staff loanOfficer = null;
Long loanOfficerId = command.getLoanOfficeId();
if (command.isLoanOfficerChanged() && loanOfficerId != null) {
loanOfficer = this.staffRepository.findOne(loanOfficerId);
if (loanOfficer == null) {
throw new LoanOfficerNotFoundException(loanOfficerId);
final Long loanOfficerId = command.getLoanOfficeId();
if (command.isOfficeIdChanged() && command.isLoanOfficerChanged()) {
/**
* Scenario: Both Office and loan officer are changed, check new
* loan officer is present in new office
*/
if (officeId != null) {
groupOffice = this.officeRepository.findOne(officeId);
if (groupOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); }
}
if (loanOfficerId != null) {
loanOfficer = this.staffRepository.findByOffice(loanOfficerId, officeId);
if (loanOfficer == null) { throw new LoanOfficerNotFoundException(loanOfficerId); }
}
} else if (command.isOfficeIdChanged()) {
/**
* Scenario: Only Office is changed, check new office has
* present loan officer, This situation is not practical as loan
* officer can't be present in two offices
*/
// TODO When office is changed need to make sure all the loan
// officer 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 (loanOfficerId != null) {
loanOfficer = this.staffRepository.findByOffice(loanOfficerId, groupForUpdate.getOfficeId());
if (loanOfficer == null) { throw new LoanOfficerNotFoundException(loanOfficerId); }
}
} else if (command.isLoanOfficerChanged()) {
/**
* Scenario: Only Loan Officer is changed, check new new loan
* officer is in present assigned office
*/
if (loanOfficerId != null) {
loanOfficer = this.staffRepository.findByOffice(loanOfficerId, groupForUpdate.getOfficeId());
if (loanOfficer == null) { throw new LoanOfficerNotFoundException(loanOfficerId); }
}
}
final Set<Client> clientMembers = assembleSetOfClients(command);
groupForUpdate.update(command, groupOffice, loanOfficer , clientMembers);
groupForUpdate.update(command, groupOffice, loanOfficer, clientMembers);
groupRepository.saveAndFlush(groupForUpdate);
this.groupRepository.saveAndFlush(groupForUpdate);
return new CommandProcessingResult(groupForUpdate.getId());
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleGroupDataIntegrityIssues(command, dve);
return new CommandProcessingResult(Long.valueOf(-1));
}
}
@Transactional
@Override
public CommandProcessingResult assignLoanOfficer(final GroupCommand command) {
this.context.authenticatedUser();
final GroupCommandValidator validator = new GroupCommandValidator(command);
validator.validateForLoanOfficerUpdate();
final Group groupForUpdate = this.groupRepository.findOne(command.getId());
if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(command.getId()); }
Staff loanOfficer = null;
final Long loanOfficerId = command.getLoanOfficeId();
if (command.isLoanOfficerChanged() && loanOfficerId != null) {
loanOfficer = this.staffRepository.findByOffice(loanOfficerId, groupForUpdate.getOfficeId());
if (loanOfficer == null) { throw new LoanOfficerNotFoundException(loanOfficerId); }
}
groupForUpdate.assigLoanOfficer(command, loanOfficer);
this.groupRepository.saveAndFlush(groupForUpdate);
return new CommandProcessingResult(groupForUpdate.getId());
}
@Transactional
@Override
public CommandProcessingResult unassignLoanOfficer(final GroupCommand command) {
this.context.authenticatedUser();
final GroupCommandValidator validator = new GroupCommandValidator(command);
validator.validateForLoanOfficerUpdate();
final Group groupForUpdate = this.groupRepository.findOne(command.getId());
if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(command.getId()); }
final Long loanOfficerId = command.getLoanOfficeId();
final Long presentLoanOfficerId = groupForUpdate.getLoanOfficerId();
if (command.isLoanOfficerChanged() && loanOfficerId != null) {
if (!loanOfficerId.equals(presentLoanOfficerId)) { throw new LoanOfficerNotFoundException(loanOfficerId); }
}
groupForUpdate.unassigLoanOfficer(command);
this.groupRepository.saveAndFlush(groupForUpdate);
return new CommandProcessingResult(groupForUpdate.getId());
}
@Transactional
@Override
public CommandProcessingResult deleteGroup(final Long groupId) {
context.authenticatedUser();
this.context.authenticatedUser();
Group groupForDelete = this.groupRepository.findOne(groupId);
if (groupForDelete == null || groupForDelete.isDeleted()) {
throw new GroupNotFoundException(groupId);
}
final Group groupForDelete = this.groupRepository.findOne(groupId);
if (groupForDelete == null || groupForDelete.isDeleted()) { throw new GroupNotFoundException(groupId); }
groupForDelete.delete();
this.groupRepository.save(groupForDelete);
@@ -165,18 +237,16 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
private Set<Client> assembleSetOfClients(final GroupCommand command) {
Set<Client> clientMembers = new HashSet<Client>();
String[] clientMembersArray = command.getClientMembers();
final Set<Client> clientMembers = new HashSet<Client>();
final String[] clientMembersArray = command.getClientMembers();
if (command.isClientMembersChanged() && !ObjectUtils.isEmpty(clientMembersArray)) {
for (String clientId : clientMembersArray) {
for (final String clientId : clientMembersArray) {
final Long id = Long.valueOf(clientId);
Client client = this.clientRepository.findOne(id);
if (client == null || client.isDeleted()) {
throw new ClientNotFoundException(id);
}
if (!client.isOfficeIdentifiedBy(command.getOfficeId())){
String errorMessage = "Group and Client must have the same office.";
final Client client = this.clientRepository.findOne(id);
if (client == null || client.isDeleted()) { throw new ClientNotFoundException(id); }
if (!client.isOfficeIdentifiedBy(command.getOfficeId())) {
final String errorMessage = "Group and Client must have the same office.";
throw new InvalidOfficeException("client", "attach.to.group", errorMessage);
}
clientMembers.add(client);
@@ -187,18 +257,20 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue is.
*/
private void handleGroupDataIntegrityIssues(final GroupCommand command, final DataIntegrityViolationException dve) {
* Guaranteed to throw an exception no matter what the data integrity issue
* is.
*/
private void handleGroupDataIntegrityIssues(final GroupCommand command, final DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
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());
} else if (realCause.getMessage().contains("name")) {
throw new PlatformDataIntegrityException("error.msg.group.duplicate.name", "Group with name {0} already exists", "name", command.getName());
}
throw new PlatformDataIntegrityException("error.msg.group.duplicate.externalId", "Group with externalId {0} already exists",
"externalId", command.getExternalId());
} else if (realCause.getMessage().contains("name")) { throw new PlatformDataIntegrityException("error.msg.group.duplicate.name",
"Group with name {0} already exists", "name", command.getName()); }
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.group.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
throw new PlatformDataIntegrityException("error.msg.group.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
}
@@ -75,7 +75,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
final Set<String> modifiedParameters = new HashSet<String>();
final Long officeId = extractLongParameter("officeId", requestMap, modifiedParameters);
final Long loanOfficeId = extractLongParameter("loanOfficerId", requestMap, modifiedParameters);
final Long loanOfficerId = extractLongParameter("loanOfficerId", requestMap, modifiedParameters);
final String externalId = extractStringParameter("externalId", requestMap, modifiedParameters);
final String name = extractStringParameter("name", requestMap, modifiedParameters);
@@ -97,7 +97,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
}
//
return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name, officeId, loanOfficeId , clientMembers);
return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name, officeId, loanOfficerId , clientMembers);
}
private void checkForUnsupportedParameters(Map<String, ?> requestMap, Set<String> supportedParams) {