From 675cebbbc7fc8e829dfe5df70868ca352253bfbf Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Wed, 24 Oct 2012 16:20:40 +0100 Subject: [PATCH] MIFOSX-67: update patch to drop recreate client identifier tables with UTF-8 charset and changes to field sizes. duplicate key scenario did not work correctly due to refetch of client data in same session which is closed due to excpetion. Little bit of removal of unused code from earlier solution. --- ...drop-recreate-client-indentifier-table.sql | 20 ++ .../api/ClientIdentifiersApiResource.java | 71 ++++--- .../mifosng/platform/api/data/ClientData.java | 27 +++ .../platform/api/data/ClientLookup.java | 2 - .../client/domain/ClientIdentifier.java | 4 +- .../domain/ClientIdentifierRepository.java | 8 +- .../service/ClientReadPlatformService.java | 12 +- .../ClientReadPlatformServiceImpl.java | 72 +++---- ...WritePlatformServiceJpaRepositoryImpl.java | 199 +++++++----------- .../DuplicateClientIdentifierException.java | 45 +++- .../service/StaffReadPlatformServiceImpl.java | 5 +- 11 files changed, 246 insertions(+), 219 deletions(-) create mode 100644 mifosng-db/patches/00003-drop-recreate-client-indentifier-table.sql diff --git a/mifosng-db/patches/00003-drop-recreate-client-indentifier-table.sql b/mifosng-db/patches/00003-drop-recreate-client-indentifier-table.sql new file mode 100644 index 000000000..d2369e7f1 --- /dev/null +++ b/mifosng-db/patches/00003-drop-recreate-client-indentifier-table.sql @@ -0,0 +1,20 @@ +drop table `m_client_identifier`; + +CREATE TABLE `m_client_identifier` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `client_id` bigint(20) NOT NULL, + `document_type_id` int(11) NOT NULL, + `document_key` varchar(50) NOT NULL, + `description` varchar(500) DEFAULT NULL, + `createdby_id` bigint(20) DEFAULT NULL, + `lastmodifiedby_id` bigint(20) DEFAULT NULL, + `created_date` datetime DEFAULT NULL, + `lastmodified_date` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unique_identifier_key` (`document_type_id`, `document_key`), + UNIQUE KEY `unique_client_identifier` (`client_id`,`document_type_id`), + KEY `FK_m_client_document_m_client` (`client_id`), + KEY `FK_m_client_document_m_code_value` (`document_type_id`), + CONSTRAINT `FK_m_client_document_m_client` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`), + CONSTRAINT `FK_m_client_document_m_code_value` FOREIGN KEY (`document_type_id`) REFERENCES `m_code_value` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientIdentifiersApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientIdentifiersApiResource.java index eb251c9a1..11b94e3c1 100755 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientIdentifiersApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientIdentifiersApiResource.java @@ -19,6 +19,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.mifosng.platform.api.commands.ClientIdentifierCommand; +import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.ClientIdentifierData; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; @@ -26,6 +27,7 @@ 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.client.service.ClientWritePlatformService; +import org.mifosng.platform.exceptions.DuplicateClientIdentifierException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -35,8 +37,6 @@ import org.springframework.stereotype.Component; @Scope("singleton") public class ClientIdentifiersApiResource { -// private final static Logger logger = LoggerFactory.getLogger(ClientIdentifiersApiResource.class); - @Autowired private ClientReadPlatformService clientReadPlatformService; @@ -105,15 +105,22 @@ public class ClientIdentifiersApiResource { @PathParam("clientId") final Long clientId, final String jsonRequestBody) { - ClientIdentifierCommand command = this.apiDataConversionService - .convertJsonToClientIdentifierCommand(null, clientId, - jsonRequestBody); - - Long clientIdentifierId = this.clientWritePlatformService - .addClientIdentifier(command); - - return Response.ok().entity(new EntityIdentifier(clientIdentifierId)) - .build(); + try { + final ClientIdentifierCommand command = this.apiDataConversionService.convertJsonToClientIdentifierCommand(null, clientId, jsonRequestBody); + + Long clientIdentifierId = this.clientWritePlatformService.addClientIdentifier(command); + + return Response.ok().entity(new EntityIdentifier(clientIdentifierId)).build(); + } + catch (DuplicateClientIdentifierException e) { + DuplicateClientIdentifierException rethrowas = e; + if (e.getDocumentTypeId() != null) { + // need to fetch client info + ClientData clientInfo = this.clientReadPlatformService.retrieveClientByIdentifier(e.getDocumentTypeId(), e.getIdentifierKey()); + rethrowas = new DuplicateClientIdentifierException(clientInfo.displayName(), clientInfo.officeName(), e.getIdentifierType(), e.getIdentifierKey()); + } + throw rethrowas; + } } @GET @@ -125,24 +132,18 @@ public class ClientIdentifiersApiResource { @PathParam("identifierId") final Long clientIdentifierId, @Context final UriInfo uriInfo) { - Set responseParameters = ApiParameterHelper - .extractFieldsForResponseIfProvided(uriInfo - .getQueryParameters()); + final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { responseParameters.addAll(typicalResponseParameters); } - boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo - .getQueryParameters()); - boolean template = ApiParameterHelper.template(uriInfo - .getQueryParameters()); - + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters()); if (template) { responseParameters.add("allowedDocumentTypes"); } - ClientIdentifierData clientIdentifierData = this.clientReadPlatformService - .retrieveClientIdentifier(clientId, clientIdentifierId); + final ClientIdentifierData clientIdentifierData = this.clientReadPlatformService.retrieveClientIdentifier(clientId, clientIdentifierId); return this.apiJsonSerializerService .serializeClientIdentifierDataToJson(prettyPrint, @@ -151,21 +152,28 @@ public class ClientIdentifiersApiResource { @PUT @Path("{identifierId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public Response updateClientIdentifer( @PathParam("clientId") final Long clientId, @PathParam("identifierId") final Long clientIdentifierId, final String jsonRequestBody) { - ClientIdentifierCommand command = this.apiDataConversionService - .convertJsonToClientIdentifierCommand(clientIdentifierId, - clientId, jsonRequestBody); + try { + final ClientIdentifierCommand command = this.apiDataConversionService.convertJsonToClientIdentifierCommand(clientIdentifierId, clientId, jsonRequestBody); - EntityIdentifier identifier = this.clientWritePlatformService - .updateClientIdentifier(command); + final EntityIdentifier identifier = this.clientWritePlatformService.updateClientIdentifier(command); - return Response.ok().entity(identifier).build(); + return Response.ok().entity(identifier).build(); + } + catch (DuplicateClientIdentifierException e) { + DuplicateClientIdentifierException reThrowAs = e; + if (e.getDocumentTypeId() != null) { + ClientData clientInfo = this.clientReadPlatformService.retrieveClientByIdentifier(e.getDocumentTypeId(), e.getIdentifierKey()); + reThrowAs = new DuplicateClientIdentifierException(clientInfo.displayName(), clientInfo.officeName(), e.getIdentifierType(), e.getIdentifierKey()); + } + throw reThrowAs; + } } @DELETE @@ -173,13 +181,10 @@ public class ClientIdentifiersApiResource { @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) public Response deleteClientIdentifier( -// @PathParam("clientId") final Long clientId, @PathParam("identifierId") final Long clientIdentifierId) { - this.clientWritePlatformService - .deleteClientIdentifier(clientIdentifierId); + this.clientWritePlatformService.deleteClientIdentifier(clientIdentifierId); return Response.ok(new EntityIdentifier(clientIdentifierId)).build(); } - } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java index 88346b222..58f78e4ce 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java @@ -6,6 +6,9 @@ import java.util.List; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; +/** + * FIXME - KW - make ClientData immutable without needs for getter/setters as is mostly intended for conversion back to JSON. + */ public class ClientData { private final Long id; @@ -19,6 +22,22 @@ public class ClientData { private final LocalDate joinedDate; private List allowedOffices = new ArrayList(); + + public static ClientData clientIdentifier( + final Long id, + final String firstname, + final String lastname, + final Long officeId, + final String officeName) { + + StringBuilder displayNameBuilder = new StringBuilder(firstname); + if (StringUtils.isNotBlank(displayNameBuilder.toString())) { + displayNameBuilder.append(' '); + } + displayNameBuilder.append(lastname); + + return new ClientData(officeId, officeName, id, firstname, lastname, displayNameBuilder.toString(), null, null); + } public ClientData(final Long officeId, final String officeName, final Long id, final String firstname, final String lastname, @@ -100,4 +119,12 @@ public class ClientData { public void setAllowedOffices(List allowedOffices) { this.allowedOffices = allowedOffices; } + + public String displayName() { + return this.displayName; + } + + public String officeName() { + return this.officeName; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientLookup.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientLookup.java index 46797c270..b967a6fed 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientLookup.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientLookup.java @@ -65,6 +65,4 @@ public class ClientLookup { public String getOfficeName() { return officeName; } - - } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifier.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifier.java index 7f3f113e4..82299bb37 100755 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifier.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifier.java @@ -55,8 +55,10 @@ public class ClientIdentifier extends AbstractAuditableCustom { this.description = StringUtils.defaultIfEmpty(description, null); } - public void update(final ClientIdentifierCommand command, + public void update( + final ClientIdentifierCommand command, final CodeValue documentType) { + if (command.isDocumentTypeChanged()) { this.documentType = documentType; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifierRepository.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifierRepository.java index 58c82fec2..23a0ca932 100755 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifierRepository.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifierRepository.java @@ -2,15 +2,9 @@ package org.mifosng.platform.client.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 ClientIdentifierRepository extends JpaRepository, JpaSpecificationExecutor { - - @Query("from ClientIdentifier ci where ci.documentType.id= :documentTypeId and ci.documentKey= :documentKey") - ClientIdentifier getClientIdentifierByDocumentTypeAndKey( - @Param("documentTypeId") Long documentTypeId, - @Param("documentKey") String documentKey); + // no behaviour } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java index 4f1563a17..e0b689f8f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java @@ -26,19 +26,11 @@ public interface ClientReadPlatformService { NoteData retrieveClientNote(Long clientId, Long noteId); - - /** - * @param clientId - * @return - */ Collection retrieveClientIdentifiers(Long clientId); ClientIdentifierData retrieveClientIdentifier(Long clientId,Long clientIdentifierId); - /** - * @return - */ ClientIdentifierData retrieveNewClientIdentifierDetails(); - Boolean existsClientIdentifier(Long clientId,Long identifierTypeId); - ClientLookup getClientByIdentifier(Long identifierTypeId, String identifierKey); + + ClientData retrieveClientByIdentifier(Long identifierTypeId, String identifierKey); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java index 5e142cc72..5ed3f4a22 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java @@ -178,14 +178,6 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService "from m_client c join m_office o on o.id = c.office_id where c.is_deleted=0 "; } - public String clientLookupByIdentifierSchema() { - return "c.id as id, c.firstname as firstname, c.lastname as lastname, " + - "c.office_id as officeId, o.name as officeName " + - "from m_client c, m_office o, m_client_identifier ci " + - "where o.id = c.office_id and c.id=ci.client_id " + - "and ci.document_type_id= ? and ci.document_key like ?"; - } - @Override public ClientLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { Long id = rs.getLong("id"); @@ -528,42 +520,46 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService } @Override - public Boolean existsClientIdentifier(Long clientId, Long identifierTypeId) { + public ClientData retrieveClientByIdentifier( + final Long identifierTypeId, + final String identifierKey) { try { - AppUser currentUser = context.authenticatedUser(); - String hierarchy = currentUser.getOffice().getHierarchy(); - String hierarchySearchString = hierarchy + "%"; + final ClientIdentifierMapper mapper = new ClientIdentifierMapper(); - ClientIdentityMapper rm = new ClientIdentityMapper(); + final String sql = "select " + mapper.clientLookupByIdentifierSchema(); - String sql = "select " + rm.schema() + " and ci.document_type_id=?"; - /****query for Object throws an exception if exactly one row is not returned***/ - this.jdbcTemplate.queryForObject(sql, rm, new Object[] { clientId, - hierarchySearchString, identifierTypeId }); - return true; - } catch (EmptyResultDataAccessException e) { - return false; - } - } - - - @Override - public ClientLookup getClientByIdentifier(Long identifierTypeId, - String identifierKey) { - try { - ClientLookupMapper mapper = new ClientLookupMapper(); - - String sql = "select " + mapper.clientLookupByIdentifierSchema(); - /**** - * query for Object throws an exception if exactly one row is not - * returned - ***/ - ClientLookup clientLookup = jdbcTemplate.queryForObject(sql, - mapper, new Object[] { identifierTypeId, identifierKey }); - return clientLookup; + return jdbcTemplate.queryForObject(sql, mapper, new Object[] { identifierTypeId, identifierKey }); } catch (EmptyResultDataAccessException e) { return null; } } + private static final class ClientIdentifierMapper implements RowMapper { + + public String clientLookupByIdentifierSchema() { + return "c.id as id, c.firstname as firstname, c.lastname as lastname, " + + "c.office_id as officeId, o.name as officeName " + + "from m_client c, m_office o, m_client_identifier ci " + + "where o.id = c.office_id and c.id=ci.client_id " + + "and ci.document_type_id= ? and ci.document_key like ?"; + } + + @Override + public ClientData mapRow(final ResultSet rs, + @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final Long id = rs.getLong("id"); + String firstname = rs.getString("firstname"); + if (StringUtils.isBlank(firstname)) { + firstname = ""; + } + final String lastname = rs.getString("lastname"); + + final Long officeId = rs.getLong("officeId"); + final String officeName = rs.getString("officeName"); + + return ClientData.clientIdentifier(id, firstname, lastname, officeId, officeName); + } + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 1a80fd5d1..2107a6bc6 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -31,11 +31,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service -public class ClientWritePlatformServiceJpaRepositoryImpl implements - ClientWritePlatformService { +public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWritePlatformService { - private final static Logger logger = LoggerFactory - .getLogger(ClientWritePlatformServiceJpaRepositoryImpl.class); + private final static Logger logger = LoggerFactory.getLogger(ClientWritePlatformServiceJpaRepositoryImpl.class); private final PlatformSecurityContext context; private final ClientRepository clientRepository; @@ -64,7 +62,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements @Override public EntityIdentifier deleteClient(final Long clientId) { - Client client = this.clientRepository.findOne(clientId); + final Client client = this.clientRepository.findOne(clientId); if (client == null || client.isDeleted()) { throw new ClientNotFoundException(clientId); } @@ -104,12 +102,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements try { context.authenticatedUser(); - ClientCommandValidator validator = new ClientCommandValidator( - command); + final ClientCommandValidator validator = new ClientCommandValidator(command); validator.validateForCreate(); - Office clientOffice = this.officeRepository.findOne(command - .getOfficeId()); + final Office clientOffice = this.officeRepository.findOne(command.getOfficeId()); if (clientOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); } @@ -141,8 +137,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements try { context.authenticatedUser(); - ClientCommandValidator validator = new ClientCommandValidator( - command); + final ClientCommandValidator validator = new ClientCommandValidator(command); validator.validateForUpdate(); Office clientOffice = null; @@ -154,8 +149,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements } } - Client clientForUpdate = this.clientRepository.findOne(command - .getId()); + final Client clientForUpdate = this.clientRepository.findOne(command.getId()); if (clientForUpdate == null || clientForUpdate.isDeleted()) { throw new ClientNotFoundException(command.getId()); } @@ -176,13 +170,12 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements context.authenticatedUser(); - Client clientForUpdate = this.clientRepository.findOne(command - .getClientId()); + final Client clientForUpdate = this.clientRepository.findOne(command.getClientId()); if (clientForUpdate == null) { throw new ClientNotFoundException(command.getClientId()); } - Note note = Note.clientNote(clientForUpdate, command.getNote()); + final Note note = Note.clientNote(clientForUpdate, command.getNote()); this.noteRepository.save(note); @@ -195,12 +188,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements context.authenticatedUser(); - Note noteForUpdate = this.noteRepository.findOne(command.getId()); + final Note noteForUpdate = this.noteRepository.findOne(command.getId()); if (noteForUpdate == null - || noteForUpdate.isNotAgainstClientWithIdOf(command - .getClientId())) { - throw new NoteNotFoundException(command.getId(), - command.getClientId(), "client"); + || noteForUpdate.isNotAgainstClientWithIdOf(command.getClientId())) { + throw new NoteNotFoundException(command.getId(),command.getClientId(), "client"); } noteForUpdate.update(command.getNote()); @@ -210,131 +201,117 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements @Transactional @Override - public Long addClientIdentifier( - ClientIdentifierCommand clientIdentifierCommand) { - CodeValue documentType = null; - String documentKey = null; + public Long addClientIdentifier(final ClientIdentifierCommand command) { + + String documentTypeLabel = null; + Long documentTypeId = null; + final String documentKey = command.getDocumentKey(); + try { context.authenticatedUser(); - ClientIdentifierCommandValidator validator = new ClientIdentifierCommandValidator( - clientIdentifierCommand); + final ClientIdentifierCommandValidator validator = new ClientIdentifierCommandValidator(command); validator.validateForCreate(); - Client client = this.clientRepository - .findOne(clientIdentifierCommand.getClientId()); - if (client == null) { - throw new ClientNotFoundException( - clientIdentifierCommand.getClientId()); + final Client client = this.clientRepository.findOne(command.getClientId()); + if (client == null || client.isDeleted()) { + throw new ClientNotFoundException(command.getClientId()); } - documentType = this.codeValueRepository - .findOne(clientIdentifierCommand.getDocumentTypeId()); + final CodeValue documentType = this.codeValueRepository.findOne(command.getDocumentTypeId()); if (documentType == null) { - throw new CodeValueNotFoundException( - clientIdentifierCommand.getDocumentTypeId()); + throw new CodeValueNotFoundException(command.getDocumentTypeId()); } + documentTypeId = documentType.getId(); + documentTypeLabel = documentType.getLabel(); - documentKey = clientIdentifierCommand.getDocumentKey(); - String description = clientIdentifierCommand.getDescription(); - - ClientIdentifier clientIdentifier = ClientIdentifier.createNew( - client, documentType, documentKey, description); + final ClientIdentifier clientIdentifier = ClientIdentifier.createNew(client, documentType, documentKey, command.getDescription()); this.clientIdentifierRepository.save(clientIdentifier); return clientIdentifier.getId(); } catch (DataIntegrityViolationException dve) { - logger.error(dve.getMessage(), dve); - if (dve.getMostSpecificCause().getMessage().contains("unique_client_identifier")) { - throw new DuplicateClientIdentifierException( - documentType.getLabel()); - }else if(dve.getMostSpecificCause().getMessage().contains("unique_identifier_key")){ - handleDuplicateClientIdentifierKeyScenario(documentType.getId(), - documentType.getLabel(), documentKey); - } - throw new PlatformDataIntegrityException( - "error.msg.clientIdentifier.unknown.data.integrity.issue", - "Unknown data integrity issue with resource."); + handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve); + return Long.valueOf(-1); } } - @Transactional @Override - public EntityIdentifier updateClientIdentifier( - ClientIdentifierCommand clientIdentifierCommand) { - CodeValue documentType = null; - Long documentTypeId = null; - ClientIdentifier clientIdentifierForUpdate = null; + public EntityIdentifier updateClientIdentifier(final ClientIdentifierCommand command) { + + String documentTypeLabel = null; + Long documentTypeId = null; + String documentKey = command.getDocumentKey(); + try { context.authenticatedUser(); - ClientIdentifierCommandValidator validator = new ClientIdentifierCommandValidator( - clientIdentifierCommand); + final ClientIdentifierCommandValidator validator = new ClientIdentifierCommandValidator(command); validator.validateForUpdate(); - documentTypeId = clientIdentifierCommand.getDocumentTypeId(); - if (clientIdentifierCommand.isDocumentTypeChanged() - && documentTypeId != null) { + CodeValue documentType = null; + documentTypeId = command.getDocumentTypeId(); + if (command.isDocumentTypeChanged() && documentTypeId != null) { documentType = this.codeValueRepository.findOne(documentTypeId); if (documentType == null) { - throw new CodeValueNotFoundException( - clientIdentifierCommand.getDocumentTypeId()); + throw new CodeValueNotFoundException(command.getDocumentTypeId()); } + documentTypeId = documentType.getId(); + documentTypeLabel = documentType.getLabel(); } - clientIdentifierForUpdate = this.clientIdentifierRepository - .findOne(clientIdentifierCommand.getId()); + final ClientIdentifier clientIdentifierForUpdate = this.clientIdentifierRepository.findOne(command.getId()); if (clientIdentifierForUpdate == null) { - throw new ClientIdentifierNotFoundException( - clientIdentifierCommand.getId()); + throw new ClientIdentifierNotFoundException(command.getId()); } - clientIdentifierForUpdate.update(clientIdentifierCommand, - documentType); + // TODO - KW - why need to check what changed when integrity violation occurs? + if (command.isDocumentTypeChanged() && command.isDocumentKeyChanged()) { + documentTypeId = command.getDocumentTypeId(); + documentKey = command.getDocumentKey(); + } else if (command.isDocumentTypeChanged() && !command.isDocumentKeyChanged()) { + documentTypeId = command.getDocumentTypeId(); + documentKey = clientIdentifierForUpdate.getDocumentKey(); + } else if (!command.isDocumentTypeChanged() && command.isDocumentKeyChanged()) { + documentTypeId = clientIdentifierForUpdate.getDocumentType().getId(); + documentKey = clientIdentifierForUpdate.getDocumentKey(); + } + + clientIdentifierForUpdate.update(command, documentType); - this.clientIdentifierRepository - .saveAndFlush(clientIdentifierForUpdate); + this.clientIdentifierRepository.saveAndFlush(clientIdentifierForUpdate); return new EntityIdentifier(clientIdentifierForUpdate.getId()); } catch (DataIntegrityViolationException dve) { - logger.error(dve.getMessage(), dve); - if (dve.getMostSpecificCause().getMessage().contains("unique_client_identifier")) { - throw new DuplicateClientIdentifierException( - documentType.getLabel()); - }else if(dve.getMostSpecificCause().getMessage().contains("unique_identifier_key")){ - /*** Throw error with details of existing customer with same identifier ***/ - if (clientIdentifierCommand.isDocumentTypeChanged() - && clientIdentifierCommand.isDocumentKeyChanged()) { - handleDuplicateClientIdentifierKeyScenario( - clientIdentifierCommand.getDocumentTypeId(), - documentType.getLabel(), - clientIdentifierCommand.getDocumentKey()); - } else if (clientIdentifierCommand.isDocumentTypeChanged() - && !clientIdentifierCommand.isDocumentKeyChanged()) { - handleDuplicateClientIdentifierKeyScenario( - clientIdentifierCommand.getDocumentTypeId(), - documentType.getLabel(), - clientIdentifierForUpdate.getDocumentKey()); - } else if (!clientIdentifierCommand.isDocumentTypeChanged() - && clientIdentifierCommand.isDocumentKeyChanged()) { - handleDuplicateClientIdentifierKeyScenario(clientIdentifierForUpdate - .getDocumentType().getId(), documentType.getLabel(), - clientIdentifierCommand.getDocumentKey()); - } - } - throw new PlatformDataIntegrityException( - "error.msg.clientIdentifier.unknown.data.integrity.issue", - "Unknown data integrity issue with resource."); + handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve); + return new EntityIdentifier(Long.valueOf(-1)); } } + private void handleClientIdentifierDataIntegrityViolation( + final String documentTypeLabel, + final Long documentTypeId, + final String documentKey, + final DataIntegrityViolationException dve) { + + if (dve.getMostSpecificCause().getMessage().contains("unique_client_identifier")) { + throw new DuplicateClientIdentifierException(documentTypeLabel); + } else if (dve.getMostSpecificCause().getMessage().contains("unique_identifier_key")) { + throw new DuplicateClientIdentifierException(documentTypeId, documentTypeLabel, documentKey); + } + + // only log as error if unexpected data integrity violation. + logger.error(dve.getMessage(), dve); + throw new PlatformDataIntegrityException( + "error.msg.clientIdentifier.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); + } + @Transactional @Override - public EntityIdentifier deleteClientIdentifier(Long clientIdentifierId) { - ClientIdentifier clientIdentifier = this.clientIdentifierRepository - .findOne(clientIdentifierId); + public EntityIdentifier deleteClientIdentifier(final Long clientIdentifierId) { + final ClientIdentifier clientIdentifier = this.clientIdentifierRepository.findOne(clientIdentifierId); if (clientIdentifier == null) { throw new ClientIdentifierNotFoundException(clientIdentifierId); } @@ -342,18 +319,4 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements return new EntityIdentifier(clientIdentifierId); } - - /** - * @param documentTypeId - * @param documentTypeLabel - * @param documentKey - */ - private void handleDuplicateClientIdentifierKeyScenario(Long documentTypeId, - String documentTypeLabel, String documentKey) { - Client client = this.clientIdentifierRepository - .getClientIdentifierByDocumentTypeAndKey(documentTypeId, documentKey).getClient(); - throw new DuplicateClientIdentifierException( - client.getDisplayName(), client.getOffice().getName(), - documentTypeLabel, documentKey); - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DuplicateClientIdentifierException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DuplicateClientIdentifierException.java index 6f7dc9122..a11444841 100755 --- a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DuplicateClientIdentifierException.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DuplicateClientIdentifierException.java @@ -1,23 +1,52 @@ package org.mifosng.platform.exceptions; /** - * A {@link RuntimeException} thrown when a client Identifer of the particular - * type is already present + * A {@link RuntimeException} thrown when a client identifier of the particular type is already present */ -public class DuplicateClientIdentifierException extends - AbstractPlatformDomainRuleException { +public class DuplicateClientIdentifierException extends AbstractPlatformDomainRuleException { - public DuplicateClientIdentifierException(String identifierType) { + private Long documentTypeId; + private String identifierKey; + private String identifierType; + + public DuplicateClientIdentifierException(final String identifierType) { super("error.msg.clientIdentifier.type.duplicate", - "Client Identifier of type " + identifierType + "Client identifier of type " + identifierType + " is already present for this client", identifierType); + this.identifierType = identifierType; + } + + public DuplicateClientIdentifierException(final Long documentTypeId, final String identifierType, final String identifierKey) { + super("error.msg.clientIdentifier.identityKey.duplicate", + "Client identifier of type " + identifierType + + " with value of " + identifierKey + " already exists.", identifierType, identifierKey); + this.documentTypeId = documentTypeId; + this.identifierType = identifierType; + this.identifierKey = identifierKey; } - public DuplicateClientIdentifierException(String clientName, - String officeName, String identifierType, String identifierKey) { + public DuplicateClientIdentifierException( + final String clientName, + final String officeName, + final String identifierType, + final String identifierKey) { super("error.msg.clientIdentifier.identityKey.duplicate", "Client " + clientName + "under " + officeName + " Branch already has a " + identifierType + " with unique key " + identifierKey, clientName, officeName, identifierType, identifierKey); + this.identifierType = identifierType; + this.identifierKey = identifierKey; + } + + public Long getDocumentTypeId() { + return documentTypeId; + } + + public String getIdentifierKey() { + return identifierKey; + } + + public String getIdentifierType() { + return identifierType; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java index 8f4079d9d..d3c816757 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java @@ -22,7 +22,8 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { private final PlatformSecurityContext context; @Autowired - public StaffReadPlatformServiceImpl(final PlatformSecurityContext context, + public StaffReadPlatformServiceImpl( + final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) { this.context = context; this.jdbcTemplate = new JdbcTemplate(dataSource); @@ -37,7 +38,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { } @Override - public StaffData mapRow(final ResultSet rs, final int rowNum) + public StaffData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { Long id = rs.getLong("id");