From 716b1fb11a804ff4d92e52eb409b6c138754d30f Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Tue, 13 Nov 2012 18:18:49 +0000 Subject: [PATCH] MIFOSX-97: WIP moving towards demo of maker checker of client create functionality. --- .../platform/api/ClientsApiResource.java | 62 ++++----- .../platform/api/MakerCheckerApiResource.java | 78 ++++++++++++ .../platform/api/commands/ClientCommand.java | 19 ++- .../mifosng/platform/api/data/ClientData.java | 119 +++++++----------- .../platform/api/data/MakerCheckerData.java | 31 +++++ ...GsonPortfolioApiJsonSerializerService.java | 28 ++++- .../PortfolioApiJsonSerializerService.java | 4 +- .../ClientReadPlatformServiceImpl.java | 28 ++--- .../api/ApiParameterHelper.java | 11 ++ .../service/LoanReadPlatformServiceImpl.java | 4 +- .../makerchecker/domain/MakerChecker.java | 14 +++ ...tfolioMakerCheckerReadPlatformService.java | 13 ++ ...ioMakerCheckerReadPlatformServiceImpl.java | 69 ++++++++++ .../PortfolioMakerCheckerServiceImpl.java | 37 ------ ...=> PortfolioMakerCheckerWriteService.java} | 3 +- ...PortfolioMakerCheckerWriteServiceImpl.java | 67 ++++++++++ .../service/CodeReadPlatformService.java | 1 + ...DepositAccountReadPlatformServiceImpl.java | 4 +- 18 files changed, 424 insertions(+), 168 deletions(-) create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/MakerCheckerApiResource.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/data/MakerCheckerData.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformService.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformServiceImpl.java delete mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java rename mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/{PortfolioMakerCheckerService.java => PortfolioMakerCheckerWriteService.java} (56%) create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteServiceImpl.java diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java index 3b18edc30..81c28ae16 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import javax.ws.rs.Consumes; @@ -28,6 +29,7 @@ import org.mifosng.platform.api.commands.NoteCommand; import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData; import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.data.MakerCheckerData; import org.mifosng.platform.api.data.NoteData; import org.mifosng.platform.api.data.OfficeLookup; import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService; @@ -40,7 +42,8 @@ import org.mifosng.platform.common.FileUtils; import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.ImageNotFoundException; import org.mifosng.platform.infrastructure.api.ApiParameterHelper; -import org.mifosng.platform.makerchecker.service.PortfolioMakerCheckerService; +import org.mifosng.platform.makerchecker.service.PortfolioMakerCheckerReadPlatformService; +import org.mifosng.platform.makerchecker.service.PortfolioMakerCheckerWriteService; import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,18 +73,17 @@ public class ClientsApiResource { private PortfolioApiDataConversionService apiDataConversionService; @Autowired - private PortfolioMakerCheckerService portfolioMakerCheckerService; + private PortfolioMakerCheckerWriteService portfolioMakerCheckerService; @Autowired private OfficeReadPlatformService officeReadPlatformService; @Autowired private PortfolioApiJsonSerializerService apiJsonSerializerService; - - private static final Set typicalResponseParameters = new HashSet( - Arrays.asList("id", "officeId", "officeName", "externalId", "firstname", "lastname", "joinedDate", "displayName", "clientOrBusinessName", "imagePresent") - ); + @Autowired + private PortfolioMakerCheckerReadPlatformService makerCheckerReadPlatformService; + @GET @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) @@ -96,13 +98,10 @@ public class ClientsApiResource { final String extraCriteria = getClientCriteria(sqlSearch, officeId, externalId, displayName, firstName, lastName, hierarchy); - Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); - if (responseParameters.isEmpty()) { - responseParameters.addAll(typicalResponseParameters); - } - boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); - Collection clients = this.clientReadPlatformService.retrieveAllIndividualClients(extraCriteria); + final Collection clients = this.clientReadPlatformService.retrieveAllIndividualClients(extraCriteria); return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clients); } @@ -159,17 +158,14 @@ public class ClientsApiResource { @PathParam("clientId") final Long clientId, @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()); + final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters()); ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); if (template) { - clientData.setAllowedOffices(new ArrayList(officeReadPlatformService.retrieveAllOfficesForLookup())); - responseParameters.add("allowedOffices"); + final List allowedOffices = new ArrayList(officeReadPlatformService.retrieveAllOfficesForLookup()); + clientData = ClientData.templateOnTop(clientData, allowedOffices); } return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData); @@ -181,14 +177,17 @@ public class ClientsApiResource { @Produces({MediaType.APPLICATION_JSON}) public String newClientDetails(@Context final UriInfo uriInfo) { - Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); - if (responseParameters.isEmpty()) { - responseParameters.addAll(typicalResponseParameters); - responseParameters.add("allowedOffices"); - } - boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters()); ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails(); + if (makerCheckerId != null) { + final MakerCheckerData entry = this.makerCheckerReadPlatformService.retrieveById(makerCheckerId); + final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, entry.json()); + + clientData = ClientData.mergeWithCommand(clientData, command); + } return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData); } @@ -198,6 +197,9 @@ public class ClientsApiResource { @Produces({MediaType.APPLICATION_JSON}) public String enrollClient(final String jsonRequestBody) { + final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, jsonRequestBody); + command.validateForCreate(); + String jsonResult = ""; // hardcode to false before checking in until configuration for enabling is done. final boolean makerCheckerEnabledForTask = false; @@ -205,8 +207,6 @@ public class ClientsApiResource { final Long makerCheckerId = this.portfolioMakerCheckerService.logNewEntry("CREATE_CLIENT", jsonRequestBody); jsonResult = this.apiJsonSerializerService.serializeEntityIdentifier(EntityIdentifier.makerChecker(makerCheckerId)); } else { - final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, jsonRequestBody); - final Long clientId = this.clientWritePlatformService.enrollClient(command); jsonResult = this.apiJsonSerializerService.serializeEntityIdentifier(new EntityIdentifier(clientId)); @@ -415,15 +415,15 @@ public class ClientsApiResource { public Response retrieveClientImage( @PathParam("clientId") final Long clientId) { - ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); + final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); //validate if client does not exist or image key is null if(clientData == null){ throw new ClientNotFoundException(clientId); } - else if(clientData.getImageKey()== null){ + else if(clientData.imageKeyDoesNotExist()){ throw new ImageNotFoundException(ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS, clientId); } - return Response.ok().entity(Base64.encodeFromFile(clientData.getImageKey())).build(); + return Response.ok().entity(Base64.encodeFromFile(clientData.imageKey())).build(); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/MakerCheckerApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/MakerCheckerApiResource.java new file mode 100644 index 000000000..e0065d3d6 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/MakerCheckerApiResource.java @@ -0,0 +1,78 @@ +package org.mifosng.platform.api; + +import java.util.Collection; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.lang.StringUtils; +import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.data.MakerCheckerData; +import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService; +import org.mifosng.platform.exceptions.UnrecognizedQueryParamException; +import org.mifosng.platform.infrastructure.api.ApiParameterHelper; +import org.mifosng.platform.makerchecker.service.PortfolioMakerCheckerReadPlatformService; +import org.mifosng.platform.makerchecker.service.PortfolioMakerCheckerWriteService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/makerchecker") +@Component +@Scope("singleton") +public class MakerCheckerApiResource { + + @Autowired + private PortfolioMakerCheckerReadPlatformService readPlatformService; + + @Autowired + private PortfolioMakerCheckerWriteService writePlatformService; + + @Autowired + private PortfolioApiJsonSerializerService apiJsonSerializerService; + + @GET + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String retrieveCodes(@Context final UriInfo uriInfo) { + + final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + + final Collection entries = this.readPlatformService.retrieveAllEntriesToBeChecked(); + + return this.apiJsonSerializerService.serializeMakerCheckerDataToJson(prettyPrint, responseParameters, entries); + } + + @POST + @Path("{makerCheckerId}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String approveMakerCheckerEntry( + @PathParam("makerCheckerId") final Long makerCheckerId, + @QueryParam("command") final String commandParam) { + + Long id = null; + if (is(commandParam, "approve")) { + id = this.writePlatformService.approveEntry(makerCheckerId); + } else { + throw new UnrecognizedQueryParamException("command", commandParam); + } + + return this.apiJsonSerializerService.serializeEntityIdentifier(EntityIdentifier.makerChecker(id)); + } + + private boolean is(final String commandParam, final String commandValue) { + return StringUtils.isNotBlank(commandParam) + && commandParam.trim().equalsIgnoreCase(commandValue); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientCommand.java index 31b37401c..070f97780 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/ClientCommand.java @@ -3,6 +3,7 @@ package org.mifosng.platform.api.commands; import java.util.Set; import org.joda.time.LocalDate; +import org.mifosng.platform.client.service.ClientCommandValidator; public class ClientCommand { @@ -15,9 +16,18 @@ public class ClientCommand { private final LocalDate joiningDate; private final Set modifiedParameters; + + private final ClientCommandValidator validator; - public ClientCommand(final Set modifiedParameters, final Long id, final String externalId, final String firstname, final String lastname, final String clientOrBusinessName, - final Long officeId, final LocalDate joiningDate) { + public ClientCommand( + final Set modifiedParameters, + final Long id, + final String externalId, + final String firstname, + final String lastname, + final String clientOrBusinessName, + final Long officeId, + final LocalDate joiningDate) { this.modifiedParameters = modifiedParameters; this.id = id; this.externalId = externalId; @@ -26,6 +36,7 @@ public class ClientCommand { this.clientOrBusinessName = clientOrBusinessName; this.officeId = officeId; this.joiningDate = joiningDate; + this.validator = new ClientCommandValidator(this); } public Long getId() { @@ -79,4 +90,8 @@ public class ClientCommand { public boolean isOfficeChanged() { return this.modifiedParameters.contains("officeId"); } + + public void validateForCreate() { + this.validator.validateForCreate(); + } } \ 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 f3f2018b0..35606afe4 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 @@ -1,15 +1,16 @@ package org.mifosng.platform.api.data; -import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; +import org.mifosng.platform.api.commands.ClientCommand; /** - * FIXME - KW - make ClientData immutable without needs for getter/setters as is mostly intended for conversion back to JSON. + * Immutable data object representing client data. */ -public class ClientData { +final public class ClientData { private final Long id; private final String firstname; @@ -21,9 +22,30 @@ public class ClientData { private final String externalId; private final LocalDate joinedDate; private final String imageKey; - private boolean imagePresent; - - private List allowedOffices = new ArrayList(); + @SuppressWarnings("unused") + private final boolean imagePresent; + private final List allowedOffices; + + // essential override existing data with data from command + public static ClientData mergeWithCommand(final ClientData clientData, final ClientCommand command) { + + final Long officeId = (Long) ObjectUtils.defaultIfNull(command.getId(), clientData.officeId); + final String firstname = (String) ObjectUtils.defaultIfNull(command.getFirstname(), clientData.firstname); + final String lastname = (String) ObjectUtils.defaultIfNull(command.getLastname(), clientData.lastname); + final String clientOrBusinessName = (String) ObjectUtils.defaultIfNull(command.getClientOrBusinessName(), clientData.clientOrBusinessName); + final String externalId = (String) ObjectUtils.defaultIfNull(command.getExternalId(), clientData.externalId); + final LocalDate joinedDate = (LocalDate) ObjectUtils.defaultIfNull(command.getJoiningDate(), clientData.joinedDate); + + return new ClientData(officeId, clientData.officeName, clientData.id, firstname, lastname, clientOrBusinessName, externalId, joinedDate, clientData.imageKey, clientData.allowedOffices); + } + + public static ClientData template(final Long officeId, final LocalDate joinedDate, final List allowedOffices) { + return new ClientData(officeId, null, null, null, null, null, null, joinedDate, null, allowedOffices); + } + + public static ClientData templateOnTop(final ClientData clientData, final List allowedOffices) { + return new ClientData(clientData.officeId, clientData.officeName, clientData.id, clientData.firstname, clientData.lastname, clientData.clientOrBusinessName, clientData.externalId, clientData.joinedDate, clientData.imageKey, allowedOffices); + } public static ClientData clientIdentifier( final Long id, @@ -38,14 +60,15 @@ public class ClientData { } displayNameBuilder.append(lastname); - return new ClientData(officeId, officeName, id, firstname, lastname, displayNameBuilder.toString(), null, null, null); + return new ClientData(officeId, officeName, id, firstname, lastname, displayNameBuilder.toString(), null, null, null, null); } public ClientData(final Long officeId, final String officeName, final Long id, final String firstname, final String lastname, final String displayName, final String externalId, final LocalDate joinedDate, - final String imageKey) { + final String imageKey, + final List allowedOffices) { this.officeId = officeId; this.officeName = officeName; this.id = id; @@ -70,64 +93,6 @@ public class ClientData { imagePresent = true; } - } - - public ClientData(final Long officeId, final LocalDate joinedDate, - final List offices) { - this.id = null; - this.officeId = officeId; - this.officeName = null; - this.firstname = null; - this.lastname = null; - this.clientOrBusinessName = null; - this.displayName = null; - this.externalId = null; - this.joinedDate = joinedDate; - this.allowedOffices = offices; - this.imageKey = null; - } - - public Long getId() { - return id; - } - - public Long getOfficeId() { - return officeId; - } - - public String getOfficeName() { - return officeName; - } - - public String getFirstname() { - return firstname; - } - - public String getLastname() { - return lastname; - } - - public String getClientOrBusinessName() { - return clientOrBusinessName; - } - - public String getDisplayName() { - return displayName; - } - - public String getExternalId() { - return externalId; - } - - public LocalDate getJoinedDate() { - return joinedDate; - } - - public List getAllowedOffices() { - return allowedOffices; - } - - public void setAllowedOffices(List allowedOffices) { this.allowedOffices = allowedOffices; } @@ -138,16 +103,24 @@ public class ClientData { public String officeName() { return this.officeName; } - - public String getImageKey() { - return imageKey; + + private boolean imageKeyExists() { + return StringUtils.isNotBlank(this.imageKey); } - public boolean isImagePresent() { - return imagePresent; + public boolean imageKeyDoesNotExist() { + return !imageKeyExists(); } - public void setImagePresent(boolean imagePresent) { - this.imagePresent = imagePresent; + public String imageKey() { + return this.imageKey; + } + + public Long id() { + return this.id; + } + + public Long officeId() { + return this.officeId; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/MakerCheckerData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/MakerCheckerData.java new file mode 100644 index 000000000..8e1936deb --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/MakerCheckerData.java @@ -0,0 +1,31 @@ +package org.mifosng.platform.api.data; + +import org.joda.time.LocalDate; + +/** + * Immutable data object representing maker-checker entry + */ +final public class MakerCheckerData { + + @SuppressWarnings("unused") + private Long id; + + @SuppressWarnings("unused") + private String taskName; + + private String taskJson; + + @SuppressWarnings("unused") + private final LocalDate madeOnDate; + + public MakerCheckerData(final Long id, final String taskName, final String taskJson, final LocalDate madeOnDate) { + this.id = id; + this.taskName = taskName; + this.taskJson = taskJson; + this.madeOnDate = madeOnDate; + } + + public String json() { + return this.taskJson; + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonPortfolioApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonPortfolioApiJsonSerializerService.java index 5f98b777d..194fc6cda 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonPortfolioApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonPortfolioApiJsonSerializerService.java @@ -30,6 +30,7 @@ import org.mifosng.platform.api.data.LoanChargeData; import org.mifosng.platform.api.data.LoanProductData; import org.mifosng.platform.api.data.LoanReassignmentData; import org.mifosng.platform.api.data.LoanTransactionData; +import org.mifosng.platform.api.data.MakerCheckerData; import org.mifosng.platform.api.data.NoteData; import org.mifosng.platform.api.data.OfficeData; import org.mifosng.platform.api.data.OfficeTransactionData; @@ -210,6 +211,9 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi private static final Set CODE_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "codename")); + private static final Set MAKER_CHECKER_DATA_PARAMETERS = new HashSet( + Arrays.asList("id", "taskName", "madeOnDate")); + private static final Set SAVINGS_ACCOUNTS_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "status", "externalId", "clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", "savingsFrequencyType", "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", "interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", @@ -699,8 +703,10 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi } @Override - public String serializeCodeDataToJson(boolean prettyPrint, - Set responseParameters, Collection codes) { + public String serializeCodeDataToJson( + final boolean prettyPrint, + final Set responseParameters, + final Collection codes) { final Gson gsonDeserializer = helper .createGsonBuilderWithParameterExclusionSerializationStrategy( CODE_DATA_PARAMETERS, prettyPrint, responseParameters); @@ -709,14 +715,28 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi } @Override - public String serializeCodeDataToJson(boolean prettyPrint, - Set responseParameters, CodeData code) { + public String serializeCodeDataToJson( + final boolean prettyPrint, + final Set responseParameters, + final CodeData code) { final Gson gsonDeserializer = helper .createGsonBuilderWithParameterExclusionSerializationStrategy( CODE_DATA_PARAMETERS, prettyPrint, responseParameters); return helper.serializedJsonFrom(gsonDeserializer, code); } + @Override + public String serializeMakerCheckerDataToJson( + final boolean prettyPrint, + final Set responseParameters, + final Collection entries) { + final Gson gsonDeserializer = helper + .createGsonBuilderWithParameterExclusionSerializationStrategy( + MAKER_CHECKER_DATA_PARAMETERS, prettyPrint, responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, + entries.toArray(new MakerCheckerData[entries.size()])); + } + @Override public String serializeSavingAccountsDataToJson(boolean prettyPrint, Set responseParameters, SavingAccountData account) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiJsonSerializerService.java index 25ef1b581..39f38c347 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiJsonSerializerService.java @@ -28,6 +28,7 @@ import org.mifosng.platform.api.data.LoanChargeData; import org.mifosng.platform.api.data.LoanProductData; import org.mifosng.platform.api.data.LoanReassignmentData; import org.mifosng.platform.api.data.LoanTransactionData; +import org.mifosng.platform.api.data.MakerCheckerData; import org.mifosng.platform.api.data.NoteData; import org.mifosng.platform.api.data.OfficeData; import org.mifosng.platform.api.data.OfficeTransactionData; @@ -134,6 +135,8 @@ public interface PortfolioApiJsonSerializerService { String serializeCodeDataToJson(boolean prettyPrint,Set responseParameters, Collection codes); String serializeCodeDataToJson(boolean prettyPrint,Set responseParameters, CodeData code); + + String serializeMakerCheckerDataToJson(boolean prettyPrint,Set responseParameters, Collection entries); String serializeSavingAccountsDataToJson(boolean prettyPrint, Set responseParameters, SavingAccountData account); @@ -141,5 +144,4 @@ public interface PortfolioApiJsonSerializerService { // TODO - KW - might devide serialize up into portfolio and account to reduce interface String serializeChartOfAccountDataToJson(boolean prettyPrint, Set responseParameters, ChartOfAccountsData chartOfAccounts); - } \ 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 e3a3b1977..f74e83868 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 @@ -128,13 +128,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService @Override public ClientData retrieveNewClientDetails() { - AppUser currentUser = context.authenticatedUser(); - - List offices = new ArrayList( - officeReadPlatformService.retrieveAllOfficesForLookup()); + final AppUser currentUser = context.authenticatedUser(); + final List offices = new ArrayList(officeReadPlatformService.retrieveAllOfficesForLookup()); final Long officeId = currentUser.getOffice().getId(); - return new ClientData(officeId, new LocalDate(), offices); + + return ClientData.template(officeId, new LocalDate(), offices); } @@ -151,22 +150,21 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService public ClientData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - Long officeId = JdbcSupport.getLong(rs, "officeId"); - Long id = JdbcSupport.getLong(rs, "id"); + final Long officeId = JdbcSupport.getLong(rs, "officeId"); + final Long id = JdbcSupport.getLong(rs, "id"); String firstname = rs.getString("firstname"); if (StringUtils.isBlank(firstname)) { firstname = ""; } - String lastname = rs.getString("lastname"); - String displayName = rs.getString("displayName"); - String externalId = rs.getString("externalId"); - LocalDate joinedDate = JdbcSupport.getLocalDate(rs, "joinedDate"); - String imageKey = rs.getString("imageKey"); - - String officeName = rs.getString("officeName"); + final String lastname = rs.getString("lastname"); + final String displayName = rs.getString("displayName"); + final String externalId = rs.getString("externalId"); + final LocalDate joinedDate = JdbcSupport.getLocalDate(rs, "joinedDate"); + final String imageKey = rs.getString("imageKey"); + final String officeName = rs.getString("officeName"); return new ClientData(officeId, officeName, id, firstname, - lastname, displayName, externalId, joinedDate,imageKey); + lastname, displayName, externalId, joinedDate,imageKey, null); } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/infrastructure/api/ApiParameterHelper.java b/mifosng-provider/src/main/java/org/mifosng/platform/infrastructure/api/ApiParameterHelper.java index ed086fe10..4f114af77 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/infrastructure/api/ApiParameterHelper.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/infrastructure/api/ApiParameterHelper.java @@ -10,6 +10,17 @@ import org.apache.commons.lang.StringUtils; public class ApiParameterHelper { + public static Long makerCheckerId(final MultivaluedMap queryParams) { + Long id = null; + if (queryParams.getFirst("makerCheckerId") != null) { + final String value = queryParams.getFirst("makerCheckerId"); + if (StringUtils.isNotBlank(value)) { + id = Long.valueOf(value); + } + } + return id; + } + public static Set extractFieldsForResponseIfProvided(final MultivaluedMap queryParams) { Set fields = new HashSet(); String commaSerperatedParameters = ""; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java index 0ff1b8535..f7711e292 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -245,8 +245,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final LocalDate expectedDisbursementDate = new LocalDate(); final ClientData clientAccount = this.clientReadPlatformService.retrieveIndividualClient(clientId); - LoanBasicDetailsData loanDetails = LoanBasicDetailsData.populateForNewIndividualClientLoanCreation(clientAccount.getId(), clientAccount.getDisplayName(), expectedDisbursementDate, - clientAccount.getOfficeId()); + LoanBasicDetailsData loanDetails = LoanBasicDetailsData.populateForNewIndividualClientLoanCreation(clientAccount.id(), clientAccount.displayName(), expectedDisbursementDate, + clientAccount.officeId()); if (productId != null) { LoanProductData selectedProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java index c727555e6..f30d50eb4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java @@ -19,6 +19,7 @@ import org.springframework.data.jpa.domain.AbstractPersistable; @Table(name = "m_maker_checker") public class MakerChecker extends AbstractPersistable { + @SuppressWarnings("unused") @Column(name = "task_name", length = 100) private String taskName; @@ -26,18 +27,22 @@ public class MakerChecker extends AbstractPersistable { private String taskJson; // should maker and checker be a staff member as opposed to just any application user? + @SuppressWarnings("unused") @ManyToOne @JoinColumn(name = "maker_id", nullable = false) private AppUser maker; + @SuppressWarnings("unused") @Column(name = "made_on_date", nullable = false) @Temporal(TemporalType.DATE) private Date madeOnDate; + @SuppressWarnings("unused") @ManyToOne @JoinColumn(name = "checker_id", nullable = true) private AppUser checker; + @SuppressWarnings("unused") @Column(name = "checked_on_date", nullable = false) @Temporal(TemporalType.DATE) private Date checkedOnDate; @@ -64,4 +69,13 @@ public class MakerChecker extends AbstractPersistable { this.maker = maker; this.madeOnDate = madeOnDate.toDate(); } + + public void markAsChecked(final AppUser checker, final LocalDate checkedOnDate) { + this.checker = checker; + this.checkedOnDate = checkedOnDate.toDate(); + } + + public String json() { + return this.taskJson; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformService.java new file mode 100644 index 000000000..5b3d024bf --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformService.java @@ -0,0 +1,13 @@ +package org.mifosng.platform.makerchecker.service; + +import java.util.Collection; + +import org.mifosng.platform.api.data.MakerCheckerData; + +public interface PortfolioMakerCheckerReadPlatformService { + + Collection retrieveAllEntriesToBeChecked(); + + MakerCheckerData retrieveById(Long id); + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformServiceImpl.java new file mode 100644 index 000000000..50a438980 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerReadPlatformServiceImpl.java @@ -0,0 +1,69 @@ +package org.mifosng.platform.makerchecker.service; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; + +import org.joda.time.LocalDate; +import org.mifosng.platform.api.data.MakerCheckerData; +import org.mifosng.platform.infrastructure.JdbcSupport; +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; + +@Service +public class PortfolioMakerCheckerReadPlatformServiceImpl implements PortfolioMakerCheckerReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + + @Autowired + public PortfolioMakerCheckerReadPlatformServiceImpl( + final PlatformSecurityContext context, + final TenantAwareRoutingDataSource dataSource) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class MakerCheckerMapper implements RowMapper { + + public String schema() { + return " mc.id as id, mc.task_name as taskName, mc.task_json as taskJson, mc.made_on_date as madeOnDate from m_maker_checker mc "; + } + + @Override + public MakerCheckerData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final Long id = rs.getLong("id"); + final String taskName = rs.getString("taskName"); + final String taskJson = rs.getString("taskJson"); + + final LocalDate madeOnDate = JdbcSupport.getLocalDate(rs, "madeOnDate"); + + return new MakerCheckerData(id, taskName, taskJson, madeOnDate); + } + } + + @Override + public Collection retrieveAllEntriesToBeChecked() { + context.authenticatedUser(); + + final MakerCheckerMapper rm = new MakerCheckerMapper(); + final String sql = "select " + rm.schema() + " order by mc.made_on_date DESC, mc.task_name ASC"; + + return this.jdbcTemplate.query(sql, rm, new Object[] {}); + } + + @Override + public MakerCheckerData retrieveById(final Long id) { + + final MakerCheckerMapper rm = new MakerCheckerMapper(); + final String sql = "select " + rm.schema() + " where mc.id=?"; + + return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {id}); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java deleted file mode 100644 index 81ab185a8..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.mifosng.platform.makerchecker.service; - -import org.joda.time.LocalDate; -import org.mifosng.platform.makerchecker.domain.MakerChecker; -import org.mifosng.platform.makerchecker.domain.MakerCheckerRepository; -import org.mifosng.platform.security.PlatformSecurityContext; -import org.mifosng.platform.user.domain.AppUser; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * - */ -@Service -public class PortfolioMakerCheckerServiceImpl implements PortfolioMakerCheckerService { - - private final PlatformSecurityContext context; - private final MakerCheckerRepository makerCheckerRepository; - - @Autowired - public PortfolioMakerCheckerServiceImpl(final PlatformSecurityContext context, final MakerCheckerRepository makerCheckerRepository) { - this.context = context; - this.makerCheckerRepository = makerCheckerRepository; - } - - @Override - public Long logNewEntry(final String taskName, final String taskJson) { - - final AppUser maker = context.authenticatedUser(); - - final MakerChecker entity = MakerChecker.makerEntry(taskName, taskJson, maker, new LocalDate()); - - makerCheckerRepository.save(entity); - - return entity.getId(); - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteService.java similarity index 56% rename from mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerService.java rename to mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteService.java index 24c203b7c..95fad39b6 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteService.java @@ -1,7 +1,8 @@ package org.mifosng.platform.makerchecker.service; -public interface PortfolioMakerCheckerService { +public interface PortfolioMakerCheckerWriteService { Long logNewEntry(String taskName, String taskJson); + Long approveEntry(Long id); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteServiceImpl.java new file mode 100644 index 000000000..be9877ff3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerWriteServiceImpl.java @@ -0,0 +1,67 @@ +package org.mifosng.platform.makerchecker.service; + +import org.joda.time.LocalDate; +import org.mifosng.platform.api.commands.ClientCommand; +import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService; +import org.mifosng.platform.client.service.ClientWritePlatformService; +import org.mifosng.platform.makerchecker.domain.MakerChecker; +import org.mifosng.platform.makerchecker.domain.MakerCheckerRepository; +import org.mifosng.platform.security.PlatformSecurityContext; +import org.mifosng.platform.user.domain.AppUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * + */ +@Service +public class PortfolioMakerCheckerWriteServiceImpl implements PortfolioMakerCheckerWriteService { + + private final PlatformSecurityContext context; + private final MakerCheckerRepository makerCheckerRepository; + private final PortfolioApiDataConversionService apiDataConversionService; + private final ClientWritePlatformService clientWritePlatformService; + + @Autowired + public PortfolioMakerCheckerWriteServiceImpl(final PlatformSecurityContext context, final MakerCheckerRepository makerCheckerRepository, + final PortfolioApiDataConversionService apiDataConversionService, + final ClientWritePlatformService clientWritePlatformService) { + this.context = context; + this.makerCheckerRepository = makerCheckerRepository; + this.apiDataConversionService = apiDataConversionService; + this.clientWritePlatformService = clientWritePlatformService; + } + + @Transactional + @Override + public Long logNewEntry(final String taskName, final String taskJson) { + + final AppUser maker = context.authenticatedUser(); + + final MakerChecker entity = MakerChecker.makerEntry(taskName, taskJson, maker, new LocalDate()); + + makerCheckerRepository.save(entity); + + return entity.getId(); + } + + @Transactional + @Override + public Long approveEntry(final Long id) { + + final AppUser checker = context.authenticatedUser(); + + final MakerChecker entity = this.makerCheckerRepository.findOne(id); + entity.markAsChecked(checker, new LocalDate()); + + makerCheckerRepository.save(entity); + + // assume client creation for now + final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, entity.json()); + + this.clientWritePlatformService.enrollClient(command); + + return entity.getId(); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeReadPlatformService.java index f3b6c78b7..28fb93560 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/CodeReadPlatformService.java @@ -5,6 +5,7 @@ import java.util.Collection; import org.mifosng.platform.api.data.CodeData; public interface CodeReadPlatformService { + Collection retrieveAllCodes(); CodeData retrieveCode(Long codeId); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java index 470d72a68..225097d48 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java @@ -99,13 +99,13 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead CurrencyData currency = new CurrencyData(selectedProduct.getCurrencyCode(), "", selectedProduct.getDigitsAfterDecimal(), "", ""); accountData = new DepositAccountData( - clientAccount.getId(), clientAccount.getDisplayName(), selectedProduct.getId(), selectedProduct.getName(), + clientAccount.id(), clientAccount.displayName(), selectedProduct.getId(), selectedProduct.getName(), currency, selectedProduct.getMinimumBalance(), selectedProduct.getMaturityDefaultInterestRate(), selectedProduct.getTenureInMonths(), selectedProduct.getInterestCompoundedEvery(), selectedProduct.getInterestCompoundedEveryPeriodType(), selectedProduct.isRenewalAllowed(), selectedProduct.isPreClosureAllowed(), selectedProduct.getPreClosureInterestRate(),selectedProduct.isInterestCompoundingAllowed()); } else { - accountData = DepositAccountData.createFrom(clientAccount.getId(), clientAccount.getDisplayName()); + accountData = DepositAccountData.createFrom(clientAccount.id(), clientAccount.displayName()); } return accountData;