Allow linking of staff to Clients

Changes required for UI to link staff to client
This commit is contained in:
mifoscontributer
2013-06-14 15:36:11 +05:30
parent 8ed65fc734
commit 7a05bb6b6a
15 changed files with 349 additions and 93 deletions
@@ -0,0 +1,5 @@
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNASSIGNSTAFF_CLIENT', 'CLIENT', 'UNASSIGNSTAFF', 0);
ALTER TABLE m_client
ADD COLUMN `staff_id` BIGINT(20) NULL DEFAULT NULL AFTER `office_id`,
ADD INDEX `client_staff_id` (`staff_id`),
ADD CONSTRAINT `FK_m_client_m_staff` FOREIGN KEY (`staff_id`) REFERENCES `m_staff` (`id`);
@@ -535,4 +535,8 @@ public class CommandWrapper {
public boolean isHolidayResource() {
return this.entityName.equalsIgnoreCase("HOLIDAY");
}
public boolean isClientUnassignStaff() {
return this.actionName.equalsIgnoreCase("UNASSIGNSTAFF") && this.entityName.equalsIgnoreCase("CLIENT");
}
}
@@ -1026,4 +1026,13 @@ public class CommandWrapperBuilder {
this.href = "/holidays/template";
return this;
}
public CommandWrapperBuilder unassignClientStaff(Long clientId) {
this.actionName = "UNASSIGNSTAFF";
this.entityName = "CLIENT";
this.entityId = clientId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "?command=unassignStaff";
return this;
}
}
@@ -157,6 +157,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = applicationContext.getBean("deleteClientCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isClientActivation()) {
handler = applicationContext.getBean("activateClientCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isClientUnassignStaff()) {
handler = applicationContext.getBean("unassignClientStaffCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
@@ -31,6 +31,7 @@ public class ClientApiConstants {
public static final String officeIdParamName = "officeId";
public static final String activeParamName = "active";
public static final String activationDateParamName = "activationDate";
public static final String staffIdParamName = "staffId";
// response parameters
public static final String statusParamName = "status";
@@ -45,14 +46,15 @@ public class ClientApiConstants {
// template related part of response
public static final String officeOptionsParamName = "officeOptions";
public static final String staffOptionsParamName = "staffOptions";
public static final Set<String> CLIENT_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName, firstnameParamName, middlenameParamName,
lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName));
lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName, staffIdParamName));
public static final Set<String> CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, accountNoParamName, externalIdParamName, firstnameParamName, middlenameParamName,
lastnameParamName, fullnameParamName, activeParamName, activationDateParamName));
lastnameParamName, fullnameParamName, activeParamName, activationDateParamName, staffIdParamName));
/**
* These parameters will match the class level parameters of
@@ -62,7 +64,7 @@ public class ClientApiConstants {
public static final Set<String> CLIENT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, accountNoParamName,
externalIdParamName, statusParamName, activeParamName, activationDateParamName, firstnameParamName, middlenameParamName,
lastnameParamName, fullnameParamName, displayNameParamName, officeIdParamName, officeNameParamName, hierarchyParamName,
imageKeyParamName, imagePresentParamName, groupsParamName, officeOptionsParamName));
imageKeyParamName, imagePresentParamName, groupsParamName, officeOptionsParamName, staffOptionsParamName));
public static final Set<String> ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, activationDateParamName));
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.client.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -37,6 +38,8 @@ import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
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.service.StaffReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
@@ -44,6 +47,7 @@ import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Path("/clients")
@Component
@@ -57,13 +61,15 @@ public class ClientsApiResource {
private final ToApiJsonSerializer<ClientAccountSummaryCollectionData> clientAccountSummaryToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final StaffReadPlatformService staffReadPlatformService;
@Autowired
public ClientsApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
final OfficeReadPlatformService officeReadPlatformService, final ToApiJsonSerializer<ClientData> toApiJsonSerializer,
final ToApiJsonSerializer<ClientAccountSummaryCollectionData> clientAccountSummaryToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final StaffReadPlatformService staffReadPlatformService) {
this.context = context;
this.clientReadPlatformService = readPlatformService;
this.officeReadPlatformService = officeReadPlatformService;
@@ -71,17 +77,18 @@ public class ClientsApiResource {
this.clientAccountSummaryToApiJsonSerializer = clientAccountSummaryToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.staffReadPlatformService = staffReadPlatformService;
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveTemplate(@Context final UriInfo uriInfo) {
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
final ClientData clientData = this.clientReadPlatformService.retrieveTemplate();
final ClientData clientData = this.clientReadPlatformService.retrieveTemplate(officeId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS);
@@ -121,7 +128,11 @@ public class ClientsApiResource {
ClientData clientData = this.clientReadPlatformService.retrieveOne(clientId);
if (settings.isTemplate()) {
final List<OfficeData> allowedOffices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOfficesForDropdown());
clientData = ClientData.templateOnTop(clientData, allowedOffices);
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(clientData.officeId());
if (CollectionUtils.isEmpty(staffOptions)) {
staffOptions = null;
}
clientData = ClientData.templateOnTop(clientData, allowedOffices, staffOptions);
}
return this.toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS);
@@ -186,11 +197,14 @@ public class ClientsApiResource {
if (is(commandParam, "activate")) {
final CommandWrapper commandRequest = builder.activateClient(clientId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "unassignStaff")) {
final CommandWrapper commandRequest = builder.unassignClientStaff(clientId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
if (result == null) {
//
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate" });
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "unassignStaff" });
}
return this.toApiJsonSerializer.serialize(result);
@@ -15,6 +15,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
/**
@@ -43,28 +44,34 @@ final public class ClientData implements Comparable<ClientData> {
private final Long imageId;
private final Boolean imagePresent;
private final Long staffId;
private final String staffName;
// associations
private final Collection<GroupGeneralData> groups;
// template
private final Collection<OfficeData> officeOptions;
private final Collection<StaffData> staffOptions;
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions) {
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, joinedDate, null, officeOptions, null);
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions,
final Collection<StaffData> staffOptions) {
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, joinedDate, null, null, null, officeOptions, null, staffOptions);
}
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeData> allowedOffices) {
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeData> allowedOffices, final Collection<StaffData> staffOptions) {
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
clientData.externalId, clientData.activationDate, clientData.imageId, allowedOffices, clientData.groups);
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName,
allowedOffices, clientData.groups, staffOptions);
}
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.officeOptions, parentGroups);
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName,
clientData.officeOptions, parentGroups, clientData.staffOptions);
}
public static ClientData clientIdentifier(final Long id, final String accountNo, final EnumOptionData status, final String firstname,
@@ -72,24 +79,25 @@ final public class ClientData implements Comparable<ClientData> {
final String officeName) {
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName, null,
null, null, null, null);
null, null, null, null, null, null,null);
}
public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
return new ClientData(null, null, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null);
return new ClientData(null, null, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null, null, null, null);
}
public static ClientData instance(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
final Long id, final String firstname, final String middlename, final String lastname, final String fullname,
final String displayName, final String externalId, final LocalDate activationDate, final Long imageId) {
final String displayName, final String externalId, final LocalDate activationDate, final Long imageId, final Long staffId,
final String staffName) {
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
externalId, activationDate, imageId, null, null);
externalId, activationDate, imageId, staffId, staffName, null, null, null);
}
private ClientData(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName, final Long id,
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
final String externalId, final LocalDate activationDate, final Long imageId, final Collection<OfficeData> allowedOffices,
final Collection<GroupGeneralData> groups) {
final String externalId, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
final Collection<OfficeData> allowedOffices, final Collection<GroupGeneralData> groups, final Collection<StaffData> staffOptions) {
this.accountNo = accountNo;
this.status = status;
if (status != null) {
@@ -113,12 +121,15 @@ final public class ClientData implements Comparable<ClientData> {
} else {
this.imagePresent = Boolean.FALSE;
}
this.staffId = staffId;
this.staffName = staffName;
// associations
this.groups = groups;
// template
this.officeOptions = allowedOffices;
this.staffOptions = staffOptions;
}
public Long id() {
@@ -9,8 +9,11 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activa
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.joda.time.LocalDate;
@@ -42,24 +45,29 @@ public final class ClientDataValidator {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_CREATE_REQUEST_DATA_PARAMETERS);
final JsonElement element = fromApiJsonHelper.parse(json);
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_CREATE_REQUEST_DATA_PARAMETERS);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
final Long officeId = fromApiJsonHelper.extractLongNamed(ClientApiConstants.officeIdParamName, element);
final Long officeId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.officeIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.officeIdParamName).value(officeId).notNull().integerGreaterThanZero();
if (fromApiJsonHelper.parameterExists(ClientApiConstants.groupIdParamName, element)) {
final Long groupId = fromApiJsonHelper.extractLongNamed(ClientApiConstants.groupIdParamName, element);
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.groupIdParamName, element)) {
final Long groupId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.groupIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.groupIdParamName).value(groupId).notNull().integerGreaterThanZero();
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
final String accountNo = fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.staffIdParamName, element)) {
final Long staffId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.staffIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.staffIdParamName).value(staffId).notNull().longGreaterThanZero();
}
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
final String accountNo = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20);
}
@@ -103,16 +111,17 @@ public final class ClientDataValidator {
}
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
final String externalId = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).ignoreIfNull()
.notExceedingLengthOf(100);
}
final Boolean active = fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
final Boolean active = this.fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
if (active != null) {
if (active.booleanValue()) {
final LocalDate joinedDate = fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName, element);
final LocalDate joinedDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName,
element);
baseDataValidator.reset().parameter(ClientApiConstants.activationDateParamName).value(joinedDate).notNull();
}
} else {
@@ -123,67 +132,67 @@ public final class ClientDataValidator {
}
private void validateIndividualNamePartsCannotBeUsedWithFullname(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final String firstnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
final String firstnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
if (StringUtils.isNotBlank(firstnameParam)) {
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam)
.mustBeBlankWhenParameterProvided(ClientApiConstants.firstnameParamName, firstnameParam);
}
final String middlenameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
final String middlenameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
if (StringUtils.isNotBlank(middlenameParam)) {
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam)
.mustBeBlankWhenParameterProvided(ClientApiConstants.middlenameParamName, middlenameParam);
}
final String lastnameParamName = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
final String lastnameParamName = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
if (StringUtils.isNotBlank(lastnameParamName)) {
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam)
.mustBeBlankWhenParameterProvided(ClientApiConstants.lastnameParamName, lastnameParamName);
}
}
private void validateRequiredIndividualNamePartsExist(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final String firstnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
final String firstnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.firstnameParamName).value(firstnameParam).notBlank()
.notExceedingLengthOf(50);
final String middlenameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
final String middlenameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.middlenameParamName).value(middlenameParam).ignoreIfNull()
.notExceedingLengthOf(50);
final String lastnameParamName = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
final String lastnameParamName = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(lastnameParamName).notBlank()
.notExceedingLengthOf(50);
}
private void fullnameCannotBeBlank(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam).notBlank().notExceedingLengthOf(100);
}
private boolean isIndividualNamePartParameterPassed(final JsonElement element) {
return fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)
|| fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)
|| fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element);
return this.fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)
|| this.fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)
|| this.fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element);
}
private boolean isFullnameParameterPassed(final JsonElement element) {
return fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element);
return this.fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element);
}
private boolean isIndividualNameProvided(final JsonElement element) {
final String firstname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
final String middlename = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
final String lastname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
final String firstname = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
final String middlename = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
final String lastname = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
return StringUtils.isNotBlank(firstname) || StringUtils.isNotBlank(middlename) || StringUtils.isNotBlank(lastname);
}
private boolean isFullnameProvided(final JsonElement element) {
final String fullname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
final String fullname = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
return StringUtils.isNotBlank(fullname);
}
@@ -192,8 +201,8 @@ public final class ClientDataValidator {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_UPDATE_REQUEST_DATA_PARAMETERS);
final JsonElement element = fromApiJsonHelper.parse(json);
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_UPDATE_REQUEST_DATA_PARAMETERS);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
@@ -201,9 +210,9 @@ public final class ClientDataValidator {
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
boolean atLeastOneParameterPassedForUpdate = false;
if (fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
atLeastOneParameterPassedForUpdate = true;
final String accountNo = fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
final String accountNo = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20);
}
@@ -247,36 +256,42 @@ public final class ClientDataValidator {
}
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element)) {
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element)) {
atLeastOneParameterPassedForUpdate = true;
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element)) {
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element)) {
atLeastOneParameterPassedForUpdate = true;
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)) {
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)) {
atLeastOneParameterPassedForUpdate = true;
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)) {
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)) {
atLeastOneParameterPassedForUpdate = true;
}
if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
atLeastOneParameterPassedForUpdate = true;
final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
final String externalId = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).notExceedingLengthOf(100);
}
final Boolean active = fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
final Boolean active = this.fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
if (active != null) {
if (active.booleanValue()) {
final LocalDate joinedDate = fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName, element);
final LocalDate joinedDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName,
element);
baseDataValidator.reset().parameter(ClientApiConstants.activationDateParamName).value(joinedDate).notNull();
}
}
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.staffIdParamName, element)) {
final Long staffId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.staffIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.staffIdParamName).value(staffId).notNull().longGreaterThanZero();
}
if (!atLeastOneParameterPassedForUpdate) {
final Object forceError = null;
baseDataValidator.reset().anyOfNotNull(forceError);
@@ -291,7 +306,7 @@ public final class ClientDataValidator {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.ACTIVATION_REQUEST_DATA_PARAMETERS);
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.ACTIVATION_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
@@ -299,7 +314,7 @@ public final class ClientDataValidator {
final JsonElement element = command.parsedJson();
final LocalDate activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
final LocalDate activationDate = this.fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
baseDataValidator.reset().parameter(activationDateParamName).value(activationDate).notNull();
throwExceptionIfValidationWarningsExist(dataValidationErrors);
@@ -311,4 +326,28 @@ public final class ClientDataValidator {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
public void validateForUnassignStaff(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParametersUnassignStaff = new HashSet<String>(Arrays.asList(ClientApiConstants.staffIdParamName));
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersUnassignStaff);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
final String staffIdParameterName = ClientApiConstants.staffIdParamName;
final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element);
baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().longGreaterThanZero();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -5,6 +5,27 @@
*/
package org.mifosplatform.portfolio.client.domain;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
@@ -16,14 +37,11 @@ import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.documentmanagement.domain.Image;
import org.mifosplatform.infrastructure.security.service.RandomPasswordGenerator;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
import org.mifosplatform.portfolio.group.domain.Group;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.*;
import java.util.*;
@Entity
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE") })
public final class Client extends AbstractPersistable<Long> {
@@ -67,6 +85,10 @@ public final class Client extends AbstractPersistable<Long> {
@Column(name = "external_id", length = 100, nullable = true, unique = true)
private String externalId;
@ManyToOne
@JoinColumn(name = "staff_id")
private Staff staff;
@ManyToMany
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
private Set<Group> groups;
@@ -74,7 +96,7 @@ public final class Client extends AbstractPersistable<Long> {
@Transient
private boolean accountNumberRequiresAutoGeneration = false;
public static Client createNew(final Office clientOffice, final Group clientParentGroup, final JsonCommand command) {
public static Client createNew(final Office clientOffice, final Group clientParentGroup, final Staff staff, final JsonCommand command) {
final String accountNo = command.stringValueOfParameterNamed(ClientApiConstants.accountNoParamName);
final String externalId = command.stringValueOfParameterNamed(ClientApiConstants.externalIdParamName);
@@ -97,7 +119,7 @@ public final class Client extends AbstractPersistable<Long> {
}
return new Client(status, clientOffice, clientParentGroup, accountNo, firstname, middlename, lastname, fullname, activationDate,
externalId);
externalId, staff);
}
protected Client() {
@@ -106,7 +128,7 @@ public final class Client extends AbstractPersistable<Long> {
private Client(final ClientStatus status, final Office office, final Group clientParentGroup, final String accountNo,
final String firstname, final String middlename, final String lastname, final String fullname, final LocalDate activationDate,
final String externalId) {
final String externalId, final Staff staff) {
if (StringUtils.isBlank(accountNo)) {
this.accountNumber = new RandomPasswordGenerator(19).generate();
this.accountNumberRequiresAutoGeneration = true;
@@ -152,6 +174,8 @@ public final class Client extends AbstractPersistable<Long> {
this.groups.add(clientParentGroup);
}
this.staff = staff;
deriveDisplayName();
validate();
}
@@ -280,6 +304,11 @@ public final class Client extends AbstractPersistable<Long> {
this.fullname = newValue;
}
if (command.isChangeInLongParameterNamed(ClientApiConstants.staffIdParamName, staffId())) {
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
actualChanges.put(ClientApiConstants.staffIdParamName, newValue);
}
final String dateFormatAsInput = command.dateFormat();
final String localeAsInput = command.locale();
@@ -326,7 +355,7 @@ public final class Client extends AbstractPersistable<Long> {
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
if (this.activationDate != null) {
if (office.isOpeningDateAfter(getActivationLocalDate())) {
if (this.office.isOpeningDateAfter(getActivationLocalDate())) {
final String defaultUserMessage = "Client activation date cannot be a date before the office opening date.";
final ApiParameterError error = ApiParameterError.parameterError(
"error.msg.clients.activationDate.cannot.be.before.office.activation.date", defaultUserMessage,
@@ -374,7 +403,7 @@ public final class Client extends AbstractPersistable<Long> {
return this.office.getId();
}
public void setImage(Image image) {
public void setImage(final Image image) {
this.image = image;
}
@@ -386,8 +415,28 @@ public final class Client extends AbstractPersistable<Long> {
return this.displayName;
}
public void setDisplayName(String displayName) {
public void setDisplayName(final String displayName) {
this.displayName = displayName;
}
private Long staffId() {
Long staffId = null;
if (this.staff != null) {
staffId = this.staff.getId();
}
return staffId;
}
public void updateStaff(final Staff staff) {
this.staff = staff;
}
public Staff getStaff() {
return this.staff;
}
public void unassignStaff() {
this.staff = null;
}
}
@@ -0,0 +1,11 @@
package org.mifosplatform.portfolio.client.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
public class ClientHasNoStaffException extends AbstractPlatformResourceNotFoundException {
public ClientHasNoStaffException(final Long clientId) {
super("error.msg.client.has.no.staff", "Client with identifier " + clientId + " does not have staff", clientId);
}
}
@@ -0,0 +1,27 @@
package org.mifosplatform.portfolio.client.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UnassignClientStaffCommandHandler implements NewCommandSourceHandler {
private final ClientWritePlatformService clientWritePlatformService;
@Autowired
public UnassignClientStaffCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
this.clientWritePlatformService = clientWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.clientWritePlatformService.unassignClientStaff(command.entityId(), command);
}
}
@@ -16,7 +16,7 @@ import org.mifosplatform.portfolio.group.service.SearchParameters;
public interface ClientReadPlatformService {
ClientData retrieveTemplate();
ClientData retrieveTemplate(Long officeId);
Page<ClientData> retrieveAll(SearchParameters searchParameters);
@@ -22,6 +22,8 @@ import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSourc
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
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.service.StaffReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData;
@@ -40,6 +42,7 @@ import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
public class ClientReadPlatformServiceImpl implements ClientReadPlatformService {
@@ -47,6 +50,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final OfficeReadPlatformService officeReadPlatformService;
private final StaffReadPlatformService staffReadPlatformService;
// data mappers
private final PaginationHelper<ClientData> paginationHelper = new PaginationHelper<ClientData>();
@@ -57,22 +61,28 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
@Autowired
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final OfficeReadPlatformService officeReadPlatformService) {
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService) {
this.context = context;
this.officeReadPlatformService = officeReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.staffReadPlatformService = staffReadPlatformService;
}
@Override
public ClientData retrieveTemplate() {
public ClientData retrieveTemplate(final Long officeId) {
final AppUser currentUser = context.authenticatedUser();
this.context.authenticatedUser();
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
final Collection<OfficeData> offices = officeReadPlatformService.retrieveAllOfficesForDropdown();
final Long officeId = currentUser.getOffice().getId();
return ClientData.template(officeId, new LocalDate(), offices);
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
if (CollectionUtils.isEmpty(staffOptions)) {
staffOptions = null;
}
return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions);
}
@Override
@@ -226,10 +236,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
sqlBuilder.append("c.office_id as officeId, o.name as officeName, ");
sqlBuilder.append("c.firstname as firstname, c.middlename as middlename, c.lastname as lastname, ");
sqlBuilder.append("c.fullname as fullname, c.display_name as displayName, ");
sqlBuilder.append("c.activation_date as activationDate, c.image_id as imageId ");
sqlBuilder.append("c.activation_date as activationDate, c.image_id as imageId, ");
sqlBuilder.append("c.staff_id as staffId, s.display_name as staffName ");
sqlBuilder.append("from m_client c ");
sqlBuilder.append("join m_office o on o.id = c.office_id ");
sqlBuilder.append("join m_group_client pgc on pgc.client_id = c.id");
sqlBuilder.append("left join m_staff s on s.id = c.staff_id ");
this.schema = sqlBuilder.toString();
}
@@ -256,9 +268,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
final Long imageId = JdbcSupport.getLong(rs, "imageId");
final String officeName = rs.getString("officeName");
final Long staffId = JdbcSupport.getLong(rs, "staffId");
final String staffName = rs.getString("staffName");
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
externalId, activationDate, imageId);
externalId, activationDate, imageId, staffId, staffName);
}
}
@@ -274,9 +288,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
builder.append("c.office_id as officeId, o.name as officeName, ");
builder.append("c.firstname as firstname, c.middlename as middlename, c.lastname as lastname, ");
builder.append("c.fullname as fullname, c.display_name as displayName, ");
builder.append("c.activation_date as activationDate, c.image_id as imageId ");
builder.append("c.activation_date as activationDate, c.image_id as imageId, ");
builder.append("c.staff_id as staffId, s.display_name as staffName ");
builder.append("from m_client c ");
builder.append("join m_office o on o.id = c.office_id ");
builder.append("left join m_staff s on s.id = c.staff_id ");
this.schema = builder.toString();
}
@@ -304,9 +320,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
final String officeName = rs.getString("officeName");
final Long imageId = JdbcSupport.getLong(rs, "imageId");
final Long staffId = JdbcSupport.getLong(rs, "staffId");
final String staffName = rs.getString("staffName");
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
externalId, activationDate, imageId);
externalId, activationDate, imageId, staffId, staffName);
}
}
@@ -560,4 +578,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
officeName);
}
}
private Long defaultToUsersOfficeIfNull(final Long officeId) {
Long defaultOfficeId = officeId;
if (defaultOfficeId == null) {
defaultOfficeId = this.context.authenticatedUser().getOffice().getId();
}
return defaultOfficeId;
}
}
@@ -18,4 +18,6 @@ public interface ClientWritePlatformService {
CommandProcessingResult deleteClient(Long clientId);
CommandProcessingResult unassignClientStaff(Long clientId, JsonCommand command);
}
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.client.service;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -20,12 +21,15 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
import org.mifosplatform.portfolio.client.data.ClientDataValidator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.client.exception.ClientHasNoStaffException;
import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
@@ -51,12 +55,13 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
private final GroupRepository groupRepository;
private final ClientDataValidator fromApiJsonDeserializer;
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
private final StaffRepositoryWrapper staffRepository;
@Autowired
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository,
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
final GroupRepository groupRepository) {
final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository) {
this.context = context;
this.clientRepository = clientRepository;
this.officeRepository = officeRepository;
@@ -64,6 +69,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
this.groupRepository = groupRepository;
this.staffRepository = staffRepository;
}
@Transactional
@@ -74,7 +80,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
if (client.isNotPending()) { throw new ClientMustBePendingToBeDeletedException(clientId); }
List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
final List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
this.noteRepository.deleteInBatch(relatedNotes);
this.clientRepository.delete(client);
@@ -92,7 +98,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
*/
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("external_id")) {
final String externalId = command.stringValueOfParameterNamed("externalId");
@@ -114,7 +120,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
public CommandProcessingResult createClient(final JsonCommand command) {
try {
context.authenticatedUser();
this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForCreate(command.json());
@@ -131,7 +137,13 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
if (clientParentGroup == null) { throw new GroupNotFoundException(groupId); }
}
final Client newClient = Client.createNew(clientOffice, clientParentGroup, command);
Staff staff = null;
final Long staffId = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
if (staffId != null) {
staff = this.staffRepository.findByOfficeWithNotFoundDetection(staffId, officeId);
}
final Client newClient = Client.createNew(clientOffice, clientParentGroup, staff, command);
this.clientRepository.save(newClient);
@@ -149,7 +161,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
.withGroupId(groupId) //
.withEntityId(newClient.getId()) //
.build();
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
@@ -160,7 +172,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
public CommandProcessingResult updateClient(final Long clientId, final JsonCommand command) {
try {
context.authenticatedUser();
this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForUpdate(command.json());
@@ -168,6 +180,16 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final Map<String, Object> changes = clientForUpdate.update(command);
if (changes.containsKey(ClientApiConstants.staffIdParamName)) {
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
Staff newStaff = null;
if (newValue != null) {
newStaff = this.staffRepository.findByOfficeWithNotFoundDetection(newValue, clientForUpdate.officeId());
}
clientForUpdate.updateStaff(newStaff);
}
if (!changes.isEmpty()) {
this.clientRepository.saveAndFlush(clientForUpdate);
}
@@ -179,7 +201,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
.withEntityId(clientId) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
@@ -207,7 +229,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
.withClientId(clientId) //
.withEntityId(clientId) //
.build();
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
@@ -216,4 +238,37 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
logger.error(dve.getMessage(), dve);
}
@Transactional
@Override
public CommandProcessingResult unassignClientStaff(final Long clientId, final JsonCommand command) {
this.context.authenticatedUser();
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(5);
this.fromApiJsonDeserializer.validateForUnassignStaff(command.json());
final Client clientForUpdate = this.clientRepository.findOneWithNotFoundDetection(clientId);
final Staff presentStaff = clientForUpdate.getStaff();
Long presentStaffId = null;
if (presentStaff == null) { throw new ClientHasNoStaffException(clientId); }
presentStaffId = presentStaff.getId();
final String staffIdParamName = ClientApiConstants.staffIdParamName;
if (!command.isChangeInLongParameterNamed(staffIdParamName, presentStaffId)) {
clientForUpdate.unassignStaff();
}
this.clientRepository.saveAndFlush(clientForUpdate);
actualChanges.put(staffIdParamName, presentStaffId);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(clientForUpdate.officeId()) //
.withEntityId(clientForUpdate.getId()) //
.withClientId(clientId) //
.with(actualChanges) //
.build();
}
}