From 721039f637449f10b2428fa9ae52418eb6a8b715 Mon Sep 17 00:00:00 2001 From: Vishwas Babu AJ Date: Sat, 6 Oct 2012 19:04:43 +0530 Subject: [PATCH] Adding services for client identifiers and some service methods for code and code value --- .../patch-0002-add-client-identifiers.sql | 26 ++ .../api/ClientIdentifiersApiResource.java | 191 ++++++++++++++ .../api/commands/ClientIdentifierCommand.java | 66 +++++ .../api/data/ClientIdentifierData.java | 73 ++++++ .../platform/api/data/CodeValueData.java | 39 +++ .../ApiDataConversionService.java | 5 +- .../ApiDataConversionServiceImpl.java | 24 ++ .../ApiJsonSerializerService.java | 5 + .../GoogleGsonApiJsonSerializerService.java | 26 ++ .../client/domain/ClientIdentifier.java | 75 ++++++ .../domain/ClientIdentifierRepository.java | 9 + .../ClientIdentifierCommandValidator.java | 65 +++++ .../service/ClientReadPlatformService.java | 17 +- .../ClientReadPlatformServiceImpl.java | 99 +++++++- .../service/ClientWritePlatformService.java | 10 + ...WritePlatformServiceJpaRepositoryImpl.java | 239 ++++++++++++++---- .../platform/common/ApplicationConstants.java | 7 + .../ClientIdentifierNotFoundException.java | 15 ++ .../CodeValueNotFoundException.java | 11 + .../platform/organisation/domain/Code.java | 30 +++ .../organisation/domain/CodeRepository.java | 9 + .../organisation/domain/CodeValue.java | 47 ++++ .../domain/CodeValueRepository.java | 9 + .../service/CodeValueReadPlatformService.java | 11 + .../CodeValueReadPlatformServiceImpl.java | 60 +++++ 25 files changed, 1112 insertions(+), 56 deletions(-) create mode 100755 mifosng-db/patches/patch-0002-add-client-identifiers.sql create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/api/ClientIdentifiersApiResource.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientIdentifierCommand.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientIdentifierData.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/api/data/CodeValueData.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifier.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifierRepository.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientIdentifierCommandValidator.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/common/ApplicationConstants.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/exceptions/ClientIdentifierNotFoundException.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/exceptions/CodeValueNotFoundException.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Code.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeRepository.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValue.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValueRepository.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformService.java create mode 100755 mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformServiceImpl.java diff --git a/mifosng-db/patches/patch-0002-add-client-identifiers.sql b/mifosng-db/patches/patch-0002-add-client-identifiers.sql new file mode 100755 index 000000000..d634aca7c --- /dev/null +++ b/mifosng-db/patches/patch-0002-add-client-identifiers.sql @@ -0,0 +1,26 @@ +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(500) NOT NULL, + `description` VARCHAR(1000) NULL DEFAULT NULL, + `createdby_id` BIGINT(20) NULL DEFAULT NULL, + `lastmodifiedby_id` BIGINT(20) NULL DEFAULT NULL, + `created_date` DATETIME NULL DEFAULT NULL, + `lastmodified_date` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `FK_m_client_document_m_client` (`client_id`), + INDEX `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`) +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; + +insert into m_code values(9,'Customer Identifier'); + +insert into m_code_value values (null,'9','Driving Licence','1'); +insert into m_code_value values (null,'9','Passport','2'); +insert into m_code_value values (null,'9','PAN Card','3'); +insert into m_code_value values (null,'9','Ration Card','4'); +insert into m_code_value values (null,'9','Other','5'); \ 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 new file mode 100755 index 000000000..c3d3b87aa --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientIdentifiersApiResource.java @@ -0,0 +1,191 @@ +package org.mifosng.platform.api; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +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.ClientLookup; +import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.infrastructure.ApiDataConversionService; +import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; +import org.mifosng.platform.api.infrastructure.ApiParameterHelper; +import org.mifosng.platform.client.service.ClientReadPlatformService; +import org.mifosng.platform.client.service.ClientWritePlatformService; +import org.mifosng.platform.organisation.service.OfficeReadPlatformService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/clients/{clientId}/identifiers") +@Component +@Scope("singleton") +public class ClientIdentifiersApiResource { + + private final static Logger logger = LoggerFactory + .getLogger(ClientIdentifiersApiResource.class); + + @Autowired + private ClientReadPlatformService clientReadPlatformService; + + @Autowired + private ClientWritePlatformService clientWritePlatformService; + + @Autowired + private ApiDataConversionService apiDataConversionService; + + @Autowired + private ApiJsonSerializerService apiJsonSerializerService; + + private static final Set typicalResponseParameters = new HashSet( + Arrays.asList("id", "clientId", "documentTypeId", "description", + "documentKey", "documentTypeName")); + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAllClientIdentifiers(@Context final UriInfo uriInfo, + @PathParam("clientId") final Long clientId) { + + Set responseParameters = ApiParameterHelper + .extractFieldsForResponseIfProvided(uriInfo + .getQueryParameters()); + if (responseParameters.isEmpty()) { + responseParameters.addAll(typicalResponseParameters); + } + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo + .getQueryParameters()); + + Collection clientIdentifiers = this.clientReadPlatformService + .retrieveClientIdentifiers(clientId); + + return this.apiJsonSerializerService + .serializeClientIdentifierDataToJson(prettyPrint, + responseParameters, clientIdentifiers); + } + + @GET + @Path("template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String newClientDetails(@Context final UriInfo uriInfo) { + + Set responseParameters = ApiParameterHelper + .extractFieldsForResponseIfProvided(uriInfo + .getQueryParameters()); + responseParameters.addAll(typicalResponseParameters); + responseParameters.add("allowedDocumentTypes"); + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo + .getQueryParameters()); + + ClientIdentifierData clientIdentifierData = this.clientReadPlatformService + .retrieveNewClientIdentifierDetails(); + + return this.apiJsonSerializerService + .serializeClientIdentifierDataToJson(prettyPrint, + responseParameters, clientIdentifierData); + } + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response createClientIdentifier( + @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(); + } + + @GET + @Path("{identifierId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getClientIdentifier( + @PathParam("clientId") final Long clientId, + @PathParam("identifierId") final Long clientIdentifierId, + @Context final UriInfo uriInfo) { + + Set responseParameters = ApiParameterHelper + .extractFieldsForResponseIfProvided(uriInfo + .getQueryParameters()); + if (responseParameters.isEmpty()) { + responseParameters.addAll(typicalResponseParameters); + } + + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo + .getQueryParameters()); + boolean template = ApiParameterHelper.template(uriInfo + .getQueryParameters()); + + if (template) { + responseParameters.add("allowedDocumentTypes"); + } + + ClientIdentifierData clientIdentifierData = this.clientReadPlatformService + .retrieveClientIdentifier(clientId, clientIdentifierId); + + return this.apiJsonSerializerService + .serializeClientIdentifierDataToJson(prettyPrint, + responseParameters, clientIdentifierData); + } + + @PUT + @Path("{identifierId}") + @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); + + EntityIdentifier identifier = this.clientWritePlatformService + .updateClientIdentifier(command); + + return Response.ok().entity(identifier).build(); + } + + @DELETE + @Path("{identifierId}") + @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); + + 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/commands/ClientIdentifierCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientIdentifierCommand.java new file mode 100755 index 000000000..fb4bca3ae --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientIdentifierCommand.java @@ -0,0 +1,66 @@ +package org.mifosng.platform.api.commands; + +import java.util.Set; + +/** + * Immutable command for creating or updating details of a client identifier. + */ +public class ClientIdentifierCommand { + + private final Long id; + private final Long clientId; + private final Long documentTypeId; + + private final String documentKey; + private final String description; + + private final Set modifiedParameters; + + public ClientIdentifierCommand(final Set modifiedParameters, + final Long id, final Long clientId, final Long documentTypeId, + final String documentKey, final String description) { + this.modifiedParameters = modifiedParameters; + this.id = id; + this.clientId = clientId; + this.documentTypeId = documentTypeId; + this.documentKey = documentKey; + this.description = description; + } + + public Long getId() { + return id; + } + + public Long getDocumentTypeId() { + return documentTypeId; + } + + public String getDocumentKey() { + return documentKey; + } + + public String getDescription() { + return description; + } + + public Set getModifiedParameters() { + return modifiedParameters; + } + + public Long getClientId() { + return clientId; + } + + public boolean isDocumentTypeChanged() { + return this.modifiedParameters.contains("documentTypeId"); + } + + public boolean isDocumentKeyChanged() { + return this.modifiedParameters.contains("documentKey"); + } + + public boolean isDescriptionChanged() { + return this.modifiedParameters.contains("description"); + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientIdentifierData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientIdentifierData.java new file mode 100755 index 000000000..83e67bc12 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientIdentifierData.java @@ -0,0 +1,73 @@ +package org.mifosng.platform.api.data; + +import java.util.ArrayList; +import java.util.List; + +public class ClientIdentifierData { + + private final Long id; + private final Long clientId; + private final Long documentTypeId; + private final String documentTypeName; + + private final String documentKey; + private final String description; + private List allowedDocumentTypes = new ArrayList(); + + public ClientIdentifierData(final Long id, final Long clientId, + final Long documentTypeId, final String documentKey, + final String description, final String documentTypeName) { + this.id = id; + this.clientId = clientId; + this.documentTypeId = documentTypeId; + this.documentKey = documentKey; + this.description = description; + this.documentTypeName = documentTypeName; + } + + public ClientIdentifierData(final Long clientId, final Long documentTypeId, + final String documentKey, final String description, + final String documentTypeName, + List allowedDocumentTypes) { + this.id = null; + this.clientId = clientId; + this.documentTypeId = documentTypeId; + this.documentKey = documentKey; + this.description = description; + this.documentTypeName = documentTypeName; + this.allowedDocumentTypes = allowedDocumentTypes; + } + + public Long getId() { + return id; + } + + public Long getClientId() { + return clientId; + } + + public Long getDocumentTypeId() { + return documentTypeId; + } + + public String getDocumentKey() { + return documentKey; + } + + public String getDescription() { + return description; + } + + public List getAllowedDocumentTypes() { + return allowedDocumentTypes; + } + + public void setAllowedDocumentTypes(List allowedDocumentTypes) { + this.allowedDocumentTypes = allowedDocumentTypes; + } + + public String getDocumentTypeName() { + return documentTypeName; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/CodeValueData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/CodeValueData.java new file mode 100755 index 000000000..3da1a8f1a --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/CodeValueData.java @@ -0,0 +1,39 @@ +package org.mifosng.platform.api.data; + +public class CodeValueData { + + private Long id; + private String name; + private Integer position; + + public CodeValueData(final Long id, final String name, + final Integer position) { + this.id = id; + this.name = name; + } + + public Long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + + public void setId(Long id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java index b7d816b5b..d29e696d1 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java @@ -4,6 +4,7 @@ import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; import org.mifosng.platform.api.commands.BranchMoneyTransferCommand; import org.mifosng.platform.api.commands.ChargeCommand; import org.mifosng.platform.api.commands.ClientCommand; +import org.mifosng.platform.api.commands.ClientIdentifierCommand; import org.mifosng.platform.api.commands.DepositAccountCommand; import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand; import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand; @@ -12,6 +13,7 @@ import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand; import org.mifosng.platform.api.commands.DepositStateTransitionCommand; import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.api.commands.GroupCommand; +import org.mifosng.platform.api.commands.LoanApplicationCommand; import org.mifosng.platform.api.commands.LoanChargeCommand; import org.mifosng.platform.api.commands.LoanProductCommand; import org.mifosng.platform.api.commands.LoanStateTransitionCommand; @@ -22,7 +24,6 @@ import org.mifosng.platform.api.commands.OrganisationCurrencyCommand; import org.mifosng.platform.api.commands.RoleCommand; import org.mifosng.platform.api.commands.SavingProductCommand; import org.mifosng.platform.api.commands.StaffCommand; -import org.mifosng.platform.api.commands.LoanApplicationCommand; import org.mifosng.platform.api.commands.UserCommand; public interface ApiDataConversionService { @@ -75,4 +76,6 @@ public interface ApiDataConversionService { DepositAccountWithdrawalCommand convertJsonToDepositWithdrawalCommand(Long resourceIdentifier, String jsonRequestBody); DepositAccountWithdrawInterestCommand convertJsonToDepositAccountWithdrawInterestCommand(Long resourceIdentifier, String jsonRequestBody); + + ClientIdentifierCommand convertJsonToClientIdentifierCommand(Long resourceIdentifier, Long clientId, String jsonRequestBody); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 84d00dde8..ce9e4311d 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -21,6 +21,7 @@ import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; import org.mifosng.platform.api.commands.BranchMoneyTransferCommand; import org.mifosng.platform.api.commands.ChargeCommand; import org.mifosng.platform.api.commands.ClientCommand; +import org.mifosng.platform.api.commands.ClientIdentifierCommand; import org.mifosng.platform.api.commands.DepositAccountCommand; import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand; import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand; @@ -1432,4 +1433,27 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { return new DepositAccountWithdrawInterestCommand(resourceIdentifier, amount, note); } + + @Override + public ClientIdentifierCommand convertJsonToClientIdentifierCommand( + Long resourceIdentifier, Long clientId, String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + Type typeOfMap = new TypeToken>(){}.getType(); + Map requestMap = gsonConverter.fromJson(json, typeOfMap); + + Set supportedParams = new HashSet(Arrays.asList("clientId", "documentTypeId", "documentKey", "description")); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + Long documentTypeId = extractLongParameter("documentTypeId", requestMap, modifiedParameters); + String documentKey = extractStringParameter("documentKey", requestMap, modifiedParameters); + String documentDescription = extractStringParameter("description", requestMap, modifiedParameters); + + return new ClientIdentifierCommand(modifiedParameters,resourceIdentifier,clientId,documentTypeId,documentKey,documentDescription); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java index 53fbb84fe..4f744313b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java @@ -10,6 +10,7 @@ import org.mifosng.platform.api.data.AuthenticatedUserData; import org.mifosng.platform.api.data.ChargeData; import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData; import org.mifosng.platform.api.data.ClientData; +import org.mifosng.platform.api.data.ClientIdentifierData; import org.mifosng.platform.api.data.ConfigurationData; import org.mifosng.platform.api.data.DatatableData; import org.mifosng.platform.api.data.DepositAccountData; @@ -117,4 +118,8 @@ public interface ApiJsonSerializerService { String serializeStaffDataToJson(boolean prettyPrint, Set responseParameters, Collection staff); String serializeEntityIdentifier(EntityIdentifier identifier); + + String serializeClientIdentifierDataToJson(boolean prettyPrint, Set responseParameters, Collection clientIdentifiers); + + String serializeClientIdentifierDataToJson(boolean prettyPrint, Set responseParameters, ClientIdentifierData clientIdentifierData); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java index e92b1d4b6..af82dedce 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java @@ -12,6 +12,7 @@ import org.mifosng.platform.api.data.AuthenticatedUserData; import org.mifosng.platform.api.data.ChargeData; import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData; import org.mifosng.platform.api.data.ClientData; +import org.mifosng.platform.api.data.ClientIdentifierData; import org.mifosng.platform.api.data.ConfigurationData; import org.mifosng.platform.api.data.DatatableData; import org.mifosng.platform.api.data.DepositAccountData; @@ -119,6 +120,10 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ Arrays.asList("id", "officeId", "officeName", "externalId", "firstname", "lastname", "joinedDate", "displayName", "clientOrBusinessName", "allowedOffices")); + + private static final Set CLIENT_IDENTIFIER_DATA_PARAMETERS = new HashSet( + Arrays.asList("id", "clientId", "documentTypeId", "documentKey", + "description", "documentTypeName" ,"allowedDocumentTypes")); private static final Set CLIENT_ACCOUNTS_DATA_PARAMETERS = new HashSet( Arrays.asList("pendingApprovalLoans", "awaitingDisbursalLoans", @@ -624,4 +629,25 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ final Gson gsonDeserializer = helper.createGsonBuilderWithParameterExclusionSerializationStrategy(DATA_PARAMETERS, false, DATA_PARAMETERS); return helper.serializedJsonFrom(gsonDeserializer, identifier); } + + @Override + public String serializeClientIdentifierDataToJson(boolean prettyPrint, + Set responseParameters, + Collection clientIdentifiers) { + final Gson gsonDeserializer = helper + .createGsonBuilderWithParameterExclusionSerializationStrategy( + CLIENT_IDENTIFIER_DATA_PARAMETERS, prettyPrint, responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, + clientIdentifiers.toArray(new ClientIdentifierData[clientIdentifiers.size()])); + } + + @Override + public String serializeClientIdentifierDataToJson(boolean prettyPrint, + Set responseParameters, + ClientIdentifierData clientIdentifierData) { + final Gson gsonDeserializer = helper + .createGsonBuilderWithParameterExclusionSerializationStrategy( + CLIENT_IDENTIFIER_DATA_PARAMETERS, prettyPrint, responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, clientIdentifierData); + } } \ 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 new file mode 100755 index 000000000..59010412f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifier.java @@ -0,0 +1,75 @@ +package org.mifosng.platform.client.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.apache.commons.lang.StringUtils; +import org.mifosng.platform.api.commands.ClientIdentifierCommand; +import org.mifosng.platform.infrastructure.AbstractAuditableCustom; +import org.mifosng.platform.organisation.domain.CodeValue; +import org.mifosng.platform.user.domain.AppUser; + +@Entity +@Table(name = "m_client_identifier") +public class ClientIdentifier extends AbstractAuditableCustom { + + @ManyToOne + @JoinColumn(name = "client_id", nullable = false) + private Client client; + + @ManyToOne + @JoinColumn(name = "document_type_id", nullable = false) + private CodeValue documentType; + + @SuppressWarnings("unused") + @Column(name = "document_key", length = 1000) + private String documentKey; + + @SuppressWarnings("unused") + @Column(name = "description", length = 1000) + private String description; + + public ClientIdentifier() { + this.client = null; + this.documentType = null; + this.documentKey = null; + this.description = null; + } + + public static ClientIdentifier createNew(Client client, + final CodeValue documentType, final String documentKey, + final String description) { + return new ClientIdentifier(client, documentType, documentKey, + description); + } + + private ClientIdentifier(Client client, final CodeValue documentType, + final String documentKey, final String description) { + this.client = client; + this.documentType = documentType; + this.documentKey = StringUtils.defaultIfEmpty(documentKey, null); + this.description = StringUtils.defaultIfEmpty(description, null); + } + + public void update(final ClientIdentifierCommand command, + final CodeValue documentType) { + if (command.isDocumentTypeChanged()) { + this.documentType = documentType; + } + + if (command.isDocumentKeyChanged()) { + this.documentKey = StringUtils.defaultIfEmpty( + command.getDocumentKey(), null); + } + + if (command.isDescriptionChanged()) { + this.description = StringUtils.defaultIfEmpty( + command.getDescription(), null); + } + + } + +} \ No newline at end of file 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 new file mode 100755 index 000000000..7dba3a39c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/ClientIdentifierRepository.java @@ -0,0 +1,9 @@ +package org.mifosng.platform.client.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface ClientIdentifierRepository extends + JpaRepository, JpaSpecificationExecutor { + // no added behaviour +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientIdentifierCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientIdentifierCommandValidator.java new file mode 100755 index 000000000..1ddd9f55d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientIdentifierCommandValidator.java @@ -0,0 +1,65 @@ +package org.mifosng.platform.client.service; + +import java.util.ArrayList; +import java.util.List; + +import org.mifosng.platform.DataValidatorBuilder; +import org.mifosng.platform.api.commands.ClientIdentifierCommand; +import org.mifosng.platform.api.data.ApiParameterError; +import org.mifosng.platform.exceptions.PlatformApiDataValidationException; + +public class ClientIdentifierCommandValidator { + + private final ClientIdentifierCommand command; + + public ClientIdentifierCommandValidator(ClientIdentifierCommand command) { + this.command = command; + } + + public void validateForUpdate() { + List dataValidationErrors = new ArrayList(); + + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder( + dataValidationErrors).resource("clientIdentifier"); + + baseDataValidator.reset().parameter("documentKey") + .value(command.getDocumentKey()).ignoreIfNull().notBlank(); + + if (command.isDocumentTypeChanged()) { + baseDataValidator.reset().parameter("documentTypeId") + .value(command.getDocumentTypeId()).notNull() + .integerGreaterThanZero(); + } + + baseDataValidator.reset().anyOfNotNull(command.getDocumentTypeId(), + command.getDocumentKey()); + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + } + + public void validateForCreate() { + List dataValidationErrors = new ArrayList(); + + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder( + dataValidationErrors).resource("clientIdentifier"); + + baseDataValidator.reset().parameter("documentTypeId") + .value(command.getDocumentTypeId()).notNull() + .integerGreaterThanZero(); + baseDataValidator.reset().parameter("clientId") + .value(command.getClientId()).notNull() + .integerGreaterThanZero(); + baseDataValidator.reset().parameter("documentKey") + .value(command.getDocumentKey()).notBlank(); + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java index c04bd8d25..34b6f8f37 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 @@ -2,8 +2,9 @@ package org.mifosng.platform.client.service; import java.util.Collection; -import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData; +import org.mifosng.platform.api.data.ClientData; +import org.mifosng.platform.api.data.ClientIdentifierData; import org.mifosng.platform.api.data.ClientLookup; import org.mifosng.platform.api.data.NoteData; @@ -22,4 +23,18 @@ public interface ClientReadPlatformService { Collection retrieveAllClientNotes(Long clientId); NoteData retrieveClientNote(Long clientId, Long noteId); + + + /** + * @param clientId + * @return + */ + Collection retrieveClientIdentifiers(Long clientId); + + ClientIdentifierData retrieveClientIdentifier(Long clientId,Long clientIdentifierId); + + /** + * @return + */ + ClientIdentifierData retrieveNewClientIdentifierDetails(); } \ 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 a9b9d9448..3ddc6c932 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 @@ -11,10 +11,12 @@ import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.mifosng.platform.api.data.*; import org.mifosng.platform.client.domain.NoteEnumerations; +import org.mifosng.platform.common.ApplicationConstants; import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.NoteNotFoundException; import org.mifosng.platform.infrastructure.JdbcSupport; import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; +import org.mifosng.platform.organisation.service.CodeValueReadPlatformService; import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.user.domain.AppUser; @@ -32,16 +34,19 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService private final PlatformSecurityContext context; private final OfficeReadPlatformService officeReadPlatformService; private final AppUserReadPlatformService appUserReadPlatformService; + private final CodeValueReadPlatformService codeValuePlatformService; @Autowired public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource, final OfficeReadPlatformService officeReadPlatformService, - final AppUserReadPlatformService appUserReadPlatformService) { + final AppUserReadPlatformService appUserReadPlatformService, + final CodeValueReadPlatformService codeValuePlatformService) { this.context = context; this.officeReadPlatformService = officeReadPlatformService; this.appUserReadPlatformService = appUserReadPlatformService; this.jdbcTemplate = new JdbcTemplate(dataSource); + this.codeValuePlatformService = codeValuePlatformService; } @@ -401,4 +406,96 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService return username; } } + + @Override + public Collection retrieveClientIdentifiers( + Long clientId) { + + AppUser currentUser = context.authenticatedUser(); + String hierarchy = currentUser.getOffice().getHierarchy(); + String hierarchySearchString = hierarchy + "%"; + + ClientIdentityMapper rm = new ClientIdentityMapper(); + + String sql = "select " + rm.schema(); + + sql += " order by ci.id"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { clientId, + hierarchySearchString }); + } + + @Override + public ClientIdentifierData retrieveClientIdentifier(Long clientId, + Long clientIdentifierId) { + AppUser currentUser = context.authenticatedUser(); + String hierarchy = currentUser.getOffice().getHierarchy(); + String hierarchySearchString = hierarchy + "%"; + + ClientIdentityMapper rm = new ClientIdentityMapper(); + + String sql = "select " + rm.schema(); + + sql += " and ci.id = ?"; + + ClientIdentifierData clientIdentifierData = this.jdbcTemplate + .queryForObject(sql, rm, new Object[] { clientId, + hierarchySearchString, clientIdentifierId }); + + if(clientIdentifierData!=null){ + clientIdentifierData.setAllowedDocumentTypes(new ArrayList( + codeValuePlatformService + .retrieveAllCodeValues(ApplicationConstants.CLIENT_IDENTITY_CODE_ID))); + } + return clientIdentifierData; + + } + + @Override + public ClientIdentifierData retrieveNewClientIdentifierDetails() { + + context.authenticatedUser(); + + List codeValueDatas = new ArrayList( + codeValuePlatformService.retrieveAllCodeValues(ApplicationConstants.CLIENT_IDENTITY_CODE_ID)); + + return new ClientIdentifierData(null,null,null,null,null,codeValueDatas); + } + + private static final class ClientIdentityMapper implements + RowMapper { + + public ClientIdentityMapper() { + } + + public String schema() { + return "ci.id as id, ci.client_id as clientId, ci.document_type_id as documentTypeId, ci.document_key as documentKey," + + " ci.description as description, cv.code_value as documentType " + + " from m_client_identifier ci, m_client c, m_office o, m_code_value cv" + + " where ci.client_id=c.id and c.office_id=o.id" + + " and ci.document_type_id=cv.id" + + " and ci.client_id = ? and o.hierarchy like ? "; + } + + @Override + public ClientIdentifierData mapRow(final ResultSet rs, + @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + Long id = JdbcSupport.getLong(rs, "id"); + Long clientId = JdbcSupport.getLong(rs, "clientId"); + Long documentTypeId = JdbcSupport.getLong(rs, "documentTypeId"); + String documentKey = rs.getString("documentKey"); + String description = rs.getString("description"); + String documentTypeName = rs.getString("documentType"); + + return new ClientIdentifierData(id, clientId, documentTypeId, + documentKey, description,documentTypeName); + } + + } + + + + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java index 6e1c362d5..b06ee6703 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java @@ -1,6 +1,7 @@ package org.mifosng.platform.client.service; import org.mifosng.platform.api.commands.ClientCommand; +import org.mifosng.platform.api.commands.ClientIdentifierCommand; import org.mifosng.platform.api.commands.NoteCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.springframework.security.access.prepost.PreAuthorize; @@ -21,4 +22,13 @@ public interface ClientWritePlatformService { @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DELETE_CLIENT_ROLE')") EntityIdentifier deleteClient(Long clientId); + + @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')") + Long addClientIdentifier(ClientIdentifierCommand clientIdentifierCommand); + + @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')") + EntityIdentifier updateClientIdentifier(ClientIdentifierCommand clientIdentifierCommand); + + @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')") + EntityIdentifier deleteClientIdentifier(Long clientIdentifierId); } \ 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 ff0e2c4c6..edd4b1011 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 @@ -2,16 +2,23 @@ package org.mifosng.platform.client.service; import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.ClientCommand; +import org.mifosng.platform.api.commands.ClientIdentifierCommand; import org.mifosng.platform.api.commands.NoteCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.client.domain.Client; +import org.mifosng.platform.client.domain.ClientIdentifier; +import org.mifosng.platform.client.domain.ClientIdentifierRepository; import org.mifosng.platform.client.domain.ClientRepository; import org.mifosng.platform.client.domain.Note; import org.mifosng.platform.client.domain.NoteRepository; +import org.mifosng.platform.exceptions.ClientIdentifierNotFoundException; import org.mifosng.platform.exceptions.ClientNotFoundException; +import org.mifosng.platform.exceptions.CodeValueNotFoundException; import org.mifosng.platform.exceptions.NoteNotFoundException; import org.mifosng.platform.exceptions.OfficeNotFoundException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException; +import org.mifosng.platform.organisation.domain.CodeValue; +import org.mifosng.platform.organisation.domain.CodeValueRepository; import org.mifosng.platform.organisation.domain.Office; import org.mifosng.platform.organisation.domain.OfficeRepository; import org.mifosng.platform.security.PlatformSecurityContext; @@ -23,151 +30,277 @@ 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; + private final ClientIdentifierRepository clientIdentifierRepository; private final OfficeRepository officeRepository; private final NoteRepository noteRepository; + private final CodeValueRepository codeValueRepository; @Autowired - public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final ClientRepository clientRepository, - final OfficeRepository officeRepository, NoteRepository noteRepository) { + public ClientWritePlatformServiceJpaRepositoryImpl( + final PlatformSecurityContext context, + final ClientRepository clientRepository, + final ClientIdentifierRepository clientIdentifierRepository, + final OfficeRepository officeRepository, + NoteRepository noteRepository, + final CodeValueRepository codeValueRepository) { this.context = context; this.clientRepository = clientRepository; + this.clientIdentifierRepository = clientIdentifierRepository; this.officeRepository = officeRepository; this.noteRepository = noteRepository; + this.codeValueRepository = codeValueRepository; } - + @Transactional @Override public EntityIdentifier deleteClient(final Long clientId) { - + Client client = this.clientRepository.findOne(clientId); if (client == null || client.isDeleted()) { throw new ClientNotFoundException(clientId); } - + client.delete(); this.clientRepository.save(client); return new EntityIdentifier(client.getId()); } - + /* - * Guaranteed to throw an exception no matter what the data integrity issue is. + * Guaranteed to throw an exception no matter what the data integrity issue + * is. */ - private void handleDataIntegrityIssues(final ClientCommand command, final DataIntegrityViolationException dve) { - + private void handleDataIntegrityIssues(final ClientCommand command, + final DataIntegrityViolationException dve) { + Throwable realCause = dve.getMostSpecificCause(); if (realCause.getMessage().contains("external_id")) { - throw new PlatformDataIntegrityException("error.msg.client.duplicate.externalId", "Client with externalId `"+ command.getExternalId() +"` already exists", "externalId", command.getExternalId()); + throw new PlatformDataIntegrityException( + "error.msg.client.duplicate.externalId", + "Client with externalId `" + command.getExternalId() + + "` already exists", "externalId", + command.getExternalId()); } - + logger.error(dve.getMessage(), dve); - throw new PlatformDataIntegrityException("error.msg.client.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); + throw new PlatformDataIntegrityException( + "error.msg.client.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); } - + @Transactional @Override public Long enrollClient(final ClientCommand command) { - try{ + try { context.authenticatedUser(); - - ClientCommandValidator validator = new ClientCommandValidator(command); + + ClientCommandValidator validator = new ClientCommandValidator( + command); validator.validateForCreate(); - - Office clientOffice = this.officeRepository.findOne(command.getOfficeId()); + + Office clientOffice = this.officeRepository.findOne(command + .getOfficeId()); if (clientOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); } - + String firstname = command.getFirstname(); String lastname = command.getLastname(); if (StringUtils.isNotBlank(command.getClientOrBusinessName())) { lastname = command.getClientOrBusinessName(); firstname = null; } - - Client newClient = Client.newClient(clientOffice, firstname, lastname, command.getJoiningDate(), command.getExternalId()); - + + Client newClient = Client + .newClient(clientOffice, firstname, lastname, + command.getJoiningDate(), command.getExternalId()); + this.clientRepository.save(newClient); - + return newClient.getId(); } catch (DataIntegrityViolationException dve) { - handleDataIntegrityIssues(command, dve); - return Long.valueOf(-1); + handleDataIntegrityIssues(command, dve); + return Long.valueOf(-1); } } - + @Transactional @Override public EntityIdentifier updateClientDetails(final ClientCommand command) { - + try { context.authenticatedUser(); - - ClientCommandValidator validator = new ClientCommandValidator(command); + + ClientCommandValidator validator = new ClientCommandValidator( + command); validator.validateForUpdate(); - + Office clientOffice = null; Long officeId = command.getOfficeId(); if (command.isOfficeChanged() && officeId != null) { clientOffice = this.officeRepository.findOne(officeId); if (clientOffice == null) { throw new OfficeNotFoundException(command.getOfficeId()); - } + } } - - Client clientForUpdate = this.clientRepository.findOne(command.getId()); + + Client clientForUpdate = this.clientRepository.findOne(command + .getId()); if (clientForUpdate == null || clientForUpdate.isDeleted()) { throw new ClientNotFoundException(command.getId()); } clientForUpdate.update(clientOffice, command); - + this.clientRepository.saveAndFlush(clientForUpdate); - + return new EntityIdentifier(clientForUpdate.getId()); } catch (DataIntegrityViolationException dve) { - handleDataIntegrityIssues(command, dve); - return new EntityIdentifier(Long.valueOf(-1)); + handleDataIntegrityIssues(command, dve); + return new EntityIdentifier(Long.valueOf(-1)); } } - + @Transactional @Override public EntityIdentifier addClientNote(final NoteCommand command) { - + context.authenticatedUser(); - - Client clientForUpdate = this.clientRepository.findOne(command.getClientId()); + + Client clientForUpdate = this.clientRepository.findOne(command + .getClientId()); if (clientForUpdate == null) { throw new ClientNotFoundException(command.getClientId()); } - + Note note = Note.clientNote(clientForUpdate, command.getNote()); - + this.noteRepository.save(note); - + return new EntityIdentifier(note.getId()); } @Transactional @Override public EntityIdentifier updateNote(final NoteCommand command) { - + context.authenticatedUser(); - + Note noteForUpdate = this.noteRepository.findOne(command.getId()); - if (noteForUpdate == null || noteForUpdate.isNotAgainstClientWithIdOf(command.getClientId())) { - throw new NoteNotFoundException(command.getId(), command.getClientId(), "client"); + if (noteForUpdate == null + || noteForUpdate.isNotAgainstClientWithIdOf(command + .getClientId())) { + throw new NoteNotFoundException(command.getId(), + command.getClientId(), "client"); } - + noteForUpdate.update(command.getNote()); - + return new EntityIdentifier(noteForUpdate.getId()); } + + @Transactional + @Override + public Long addClientIdentifier(ClientIdentifierCommand clientIdentifierCommand) { + try { + context.authenticatedUser(); + + ClientIdentifierCommandValidator validator = new ClientIdentifierCommandValidator( + clientIdentifierCommand); + validator.validateForCreate(); + + Client client = this.clientRepository + .findOne(clientIdentifierCommand.getClientId()); + if (client == null) { + throw new ClientNotFoundException( + clientIdentifierCommand.getClientId()); + } + + CodeValue documentType = this.codeValueRepository + .findOne(clientIdentifierCommand.getDocumentTypeId()); + if (documentType == null) { + throw new CodeValueNotFoundException( + clientIdentifierCommand.getDocumentTypeId()); + } + + String documentKey = clientIdentifierCommand.getDocumentKey(); + String description = clientIdentifierCommand.getDescription(); + + ClientIdentifier clientIdentifier = ClientIdentifier.createNew( + client, documentType, documentKey, description); + + this.clientIdentifierRepository.save(clientIdentifier); + + return clientIdentifier.getId(); + } catch (DataIntegrityViolationException dve) { + logger.error(dve.getMessage(), dve); + throw new PlatformDataIntegrityException( + "error.msg.clientIdentifier.unknown.data.integrity.issue", + "Unknown data integrity issue with resource."); + } + } + + @Override + public EntityIdentifier updateClientIdentifier( + ClientIdentifierCommand clientIdentifierCommand) { + + try { + context.authenticatedUser(); + + ClientIdentifierCommandValidator validator = new ClientIdentifierCommandValidator( + clientIdentifierCommand); + validator.validateForUpdate(); + + CodeValue documentType = null; + Long documentTypeId = clientIdentifierCommand.getDocumentTypeId(); + if (clientIdentifierCommand.isDocumentTypeChanged() + && documentTypeId != null) { + documentType = this.codeValueRepository.findOne(documentTypeId); + if (documentType == null) { + throw new CodeValueNotFoundException( + clientIdentifierCommand.getDocumentTypeId()); + } + } + + ClientIdentifier clientIdentifierForUpdate = this.clientIdentifierRepository + .findOne(clientIdentifierCommand.getId()); + if (clientIdentifierForUpdate == null) { + throw new ClientIdentifierNotFoundException( + clientIdentifierCommand.getId()); + } + clientIdentifierForUpdate.update(clientIdentifierCommand, + documentType); + + this.clientIdentifierRepository + .saveAndFlush(clientIdentifierForUpdate); + + return new EntityIdentifier(clientIdentifierForUpdate.getId()); + } catch (DataIntegrityViolationException dve) { + 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); + if (clientIdentifier == null) { + throw new ClientIdentifierNotFoundException(clientIdentifierId); + } + this.clientIdentifierRepository.delete(clientIdentifier); + + return new EntityIdentifier(clientIdentifierId); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/common/ApplicationConstants.java b/mifosng-provider/src/main/java/org/mifosng/platform/common/ApplicationConstants.java new file mode 100755 index 000000000..4cc9567ab --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/common/ApplicationConstants.java @@ -0,0 +1,7 @@ +package org.mifosng.platform.common; + +public class ApplicationConstants { + + public static final Long CLIENT_IDENTITY_CODE_ID = 9L; + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/ClientIdentifierNotFoundException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/ClientIdentifierNotFoundException.java new file mode 100755 index 000000000..ab18e2296 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/ClientIdentifierNotFoundException.java @@ -0,0 +1,15 @@ +package org.mifosng.platform.exceptions; + +/** + * A {@link RuntimeException} thrown when client Identifier resources are not + * found. + */ +public class ClientIdentifierNotFoundException extends + AbstractPlatformResourceNotFoundException { + + public ClientIdentifierNotFoundException(Long id) { + super("error.msg.clientIdentifier.id.invalid", + "Client Identifier with the primary key " + id + + " does not exist", id); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/CodeValueNotFoundException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/CodeValueNotFoundException.java new file mode 100755 index 000000000..7f7bfa84e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/CodeValueNotFoundException.java @@ -0,0 +1,11 @@ +package org.mifosng.platform.exceptions; + +/** + * A {@link RuntimeException} thrown when client resources are not found. + */ +public class CodeValueNotFoundException extends AbstractPlatformResourceNotFoundException { + + public CodeValueNotFoundException(Long id) { + super("error.msg.client.id.invalid", "Code value with identifier " + id + " does not exist", id); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Code.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Code.java new file mode 100755 index 000000000..ece7f04cd --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Code.java @@ -0,0 +1,30 @@ +package org.mifosng.platform.organisation.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_code", uniqueConstraints = { @UniqueConstraint(columnNames = { "code_name" }, name = "code_name") }) +public class Code extends AbstractPersistable { + + @SuppressWarnings("unused") + @Column(name = "code_name", length = 100) + private String codeName; + + public static Code createNew(final String codeName) { + return new Code(codeName); + } + + protected Code() { + // + } + + private Code(final String codeName) { + this.codeName = codeName; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeRepository.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeRepository.java new file mode 100755 index 000000000..ff70ef8b8 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeRepository.java @@ -0,0 +1,9 @@ +package org.mifosng.platform.organisation.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface CodeRepository extends JpaRepository, + JpaSpecificationExecutor { + // no added behaviour +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValue.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValue.java new file mode 100755 index 000000000..39748d097 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValue.java @@ -0,0 +1,47 @@ +package org.mifosng.platform.organisation.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +import org.apache.commons.lang.StringUtils; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_code_value", uniqueConstraints = { @UniqueConstraint(columnNames = { + "code_id", "code_value" }, name = "code_value_duplicate") }) +public class CodeValue extends AbstractPersistable { + + @SuppressWarnings("unused") + @Column(name = "code_value", length = 100) + private String label; + + @SuppressWarnings("unused") + @Column(name = "order_position") + private int position; + + // Code to which this value belongs + @SuppressWarnings("unused") + @ManyToOne + @JoinColumn(name = "code_id", nullable = false) + private Code code; + + public static CodeValue createNew(Code code, final String label, + final int position) { + return new CodeValue(code, label, position); + } + + protected CodeValue() { + // + } + + private CodeValue(final Code code, final String label, final int position) { + this.code = code; + this.label = StringUtils.defaultIfEmpty(label, null); + this.position = position; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValueRepository.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValueRepository.java new file mode 100755 index 000000000..14114f183 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/CodeValueRepository.java @@ -0,0 +1,9 @@ +package org.mifosng.platform.organisation.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface CodeValueRepository extends JpaRepository, + JpaSpecificationExecutor { + // no added behaviour +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformService.java new file mode 100755 index 000000000..ce15dd38a --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformService.java @@ -0,0 +1,11 @@ +package org.mifosng.platform.organisation.service; + +import java.util.Collection; + +import org.mifosng.platform.api.data.CodeValueData; + +public interface CodeValueReadPlatformService { + + Collection retrieveAllCodeValues(Long codeId); + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformServiceImpl.java new file mode 100755 index 000000000..7b08b7133 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeValueReadPlatformServiceImpl.java @@ -0,0 +1,60 @@ +package org.mifosng.platform.organisation.service; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; + +import org.mifosng.platform.api.data.CodeValueData; +import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; +import org.mifosng.platform.security.PlatformSecurityContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CodeValueReadPlatformServiceImpl implements CodeValueReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + + @Autowired + public CodeValueReadPlatformServiceImpl(final PlatformSecurityContext context, + final TenantAwareRoutingDataSource dataSource) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class CodeValueDataMapper implements + RowMapper { + + public String schema() { + return " cv.id as id,cv.code_value as value,cv.code_id as codeId, cv.order_position as position" + + " from m_code_value as cv "; + } + + @Override + public CodeValueData mapRow(final ResultSet rs, final int rowNum) + throws SQLException { + + Long id = rs.getLong("id"); + String value = rs.getString("value"); + Integer position = rs.getInt("position"); + + return new CodeValueData(id, value, position); + } + } + + @Override + public Collection retrieveAllCodeValues(Long codeId) { + context.authenticatedUser(); + + CodeValueDataMapper rm = new CodeValueDataMapper(); + String sql = "select " + rm.schema() + + "where cv.code_id = ? order by position"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { codeId }); + } + +} \ No newline at end of file