MIFOSX-97: wip on supporting maker checker approach in platform starting with clients flow.
This commit is contained in:
@@ -24,7 +24,6 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosng.platform.api.commands.ClientCommand;
|
||||
import org.mifosng.platform.api.commands.NoteCommand;
|
||||
import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData;
|
||||
import org.mifosng.platform.api.data.ClientData;
|
||||
@@ -159,7 +158,7 @@ public class ClientsApiResource {
|
||||
@Path("{clientId}")
|
||||
@Consumes({MediaType.APPLICATION_JSON})
|
||||
@Produces({MediaType.APPLICATION_JSON})
|
||||
public String retrieveClientData(
|
||||
public String retrieveClient(
|
||||
@PathParam("clientId") final Long clientId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
@@ -176,15 +175,46 @@ public class ClientsApiResource {
|
||||
clientData = ClientData.templateOnTop(clientData, allowedOffices);
|
||||
}
|
||||
if (makerCheckerId != null) {
|
||||
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
|
||||
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, entry.json(), false);
|
||||
|
||||
clientData = ClientData.integrateChanges(clientData, command);
|
||||
clientData = handleMakerCheckerRequest(clientId, makerCheckerId, clientData);
|
||||
}
|
||||
|
||||
boolean retrieveChanges = true;
|
||||
if (retrieveChanges) {
|
||||
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
|
||||
clientData = ClientData.integrateChanges(clientData, clientData.currentChange(), dataChanges);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
|
||||
}
|
||||
|
||||
private ClientData handleMakerCheckerRequest(final Long clientId, final Long makerCheckerId, ClientData clientData) {
|
||||
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
|
||||
final ClientData currentChange = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, entry.json());
|
||||
|
||||
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
|
||||
clientData = ClientData.integrateChanges(clientData, currentChange, dataChanges);
|
||||
return clientData;
|
||||
}
|
||||
|
||||
private Collection<ClientData> retrieveAllUnprocessedDataChanges(final Long clientId) {
|
||||
Collection<ClientData> dataChanges = new ArrayList<ClientData>();
|
||||
|
||||
boolean retrieveChanges = true;
|
||||
if (retrieveChanges) {
|
||||
Collection<CommandSourceData> unprocessedChanges = this.commandSourceReadPlatformService.retrieveUnprocessChangesByResourceId("clients", clientId);
|
||||
for (CommandSourceData commandSourceData : unprocessedChanges) {
|
||||
ClientData change = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, commandSourceData.json());
|
||||
dataChanges.add(change);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataChanges.isEmpty()) {
|
||||
dataChanges = null;
|
||||
}
|
||||
|
||||
return dataChanges;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({MediaType.APPLICATION_JSON})
|
||||
@@ -199,10 +229,7 @@ public class ClientsApiResource {
|
||||
|
||||
ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
|
||||
if (makerCheckerId != null) {
|
||||
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
|
||||
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, entry.json(), false);
|
||||
|
||||
clientData = ClientData.integrateChanges(clientData, command);
|
||||
clientData = handleMakerCheckerRequest(null, makerCheckerId, clientData);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.joda.time.LocalDate;
|
||||
*/
|
||||
public class ClientCommand {
|
||||
|
||||
private final Long id;
|
||||
private final String externalId;
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
@@ -18,6 +17,7 @@ public class ClientCommand {
|
||||
private final LocalDate joiningDate;
|
||||
|
||||
// made transient as dont want them to be serialized/converted to JSON
|
||||
private final transient Long id;
|
||||
private final transient boolean makerCheckerApproval;
|
||||
private final transient Set<String> parametersPassedInRequest;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.mifosng.platform.api.data;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosng.platform.api.commands.ClientCommand;
|
||||
|
||||
/**
|
||||
* Immutable data object representing client data.
|
||||
@@ -22,13 +22,13 @@ final public class ClientData {
|
||||
private final LocalDate joinedDate;
|
||||
private final String imageKey;
|
||||
@SuppressWarnings("unused")
|
||||
private final boolean imagePresent;
|
||||
private final Boolean imagePresent;
|
||||
|
||||
private final List<OfficeLookup> allowedOffices;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final ClientCommand changes;
|
||||
|
||||
private final ClientData currentChange;
|
||||
private final Collection<ClientData> allChanges;
|
||||
|
||||
private static String buildDisplayNameFrom(final String firstname, final String lastname) {
|
||||
String displayName = null;
|
||||
StringBuilder displayNameBuilder = new StringBuilder();
|
||||
@@ -43,7 +43,27 @@ final public class ClientData {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public static ClientData integrateChanges(final ClientData clientData, final ClientCommand command) {
|
||||
public static ClientData dataChangeInstance(
|
||||
final Long id,
|
||||
final Long officeId,
|
||||
final String externalId,
|
||||
final String firstname,
|
||||
final String lastname,
|
||||
final String clientOrBusinessName,
|
||||
final LocalDate joiningDate) {
|
||||
|
||||
String firstnameValue = firstname;
|
||||
String lastnameValue = lastname;
|
||||
if (StringUtils.isNotBlank(clientOrBusinessName)) {
|
||||
firstnameValue = null;
|
||||
lastnameValue = clientOrBusinessName;
|
||||
}
|
||||
final String displayName = buildDisplayNameFrom(firstnameValue, lastnameValue);
|
||||
|
||||
return new ClientData(officeId, null, id, firstname, lastname, displayName, externalId, joiningDate, null, null, null, null);
|
||||
}
|
||||
|
||||
public static ClientData integrateChanges(final ClientData clientData, ClientData currentChange, final Collection<ClientData> allChanges) {
|
||||
String firstname = clientData.firstname;
|
||||
String lastname = clientData.lastname;
|
||||
if (StringUtils.isNotBlank(clientData.clientOrBusinessName)) {
|
||||
@@ -52,11 +72,11 @@ final public class ClientData {
|
||||
}
|
||||
final String displayName = buildDisplayNameFrom(firstname, lastname);
|
||||
return new ClientData(clientData.officeId, clientData.officeName, clientData.id, firstname, lastname, displayName,
|
||||
clientData.externalId, clientData.joinedDate, clientData.imageKey, clientData.allowedOffices, command);
|
||||
clientData.externalId, clientData.joinedDate, clientData.imageKey, clientData.allowedOffices, currentChange, allChanges);
|
||||
}
|
||||
|
||||
public static ClientData template(final Long officeId, final LocalDate joinedDate, final List<OfficeLookup> allowedOffices) {
|
||||
return new ClientData(officeId, null, null, null, null, null, null, joinedDate, null, allowedOffices, null);
|
||||
return new ClientData(officeId, null, null, null, null, null, null, joinedDate, null, allowedOffices, null, null);
|
||||
}
|
||||
|
||||
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeLookup> allowedOffices) {
|
||||
@@ -69,7 +89,7 @@ final public class ClientData {
|
||||
}
|
||||
final String displayName = buildDisplayNameFrom(firstname, lastname);
|
||||
return new ClientData(clientData.officeId, clientData.officeName, clientData.id, firstname, lastname, displayName,
|
||||
clientData.externalId, clientData.joinedDate, clientData.imageKey, allowedOffices, null);
|
||||
clientData.externalId, clientData.joinedDate, clientData.imageKey, allowedOffices, clientData.currentChange, clientData.allChanges);
|
||||
}
|
||||
|
||||
public static ClientData clientIdentifier(
|
||||
@@ -81,7 +101,7 @@ final public class ClientData {
|
||||
|
||||
final String displayName = buildDisplayNameFrom(firstname, lastname);
|
||||
|
||||
return new ClientData(officeId, officeName, id, firstname, lastname, displayName, null, null, null, null, null);
|
||||
return new ClientData(officeId, officeName, id, firstname, lastname, displayName, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public ClientData(
|
||||
@@ -95,7 +115,8 @@ final public class ClientData {
|
||||
final LocalDate joinedDate,
|
||||
final String imageKey,
|
||||
final List<OfficeLookup> allowedOffices,
|
||||
final ClientCommand changes) {
|
||||
final ClientData currentChange,
|
||||
final Collection<ClientData> allChanges) {
|
||||
this.officeId = officeId;
|
||||
this.officeName = officeName;
|
||||
this.id = id;
|
||||
@@ -113,9 +134,14 @@ final public class ClientData {
|
||||
this.externalId = externalId;
|
||||
this.joinedDate = joinedDate;
|
||||
this.imageKey = imageKey;
|
||||
this.imagePresent = (imageKey != null);
|
||||
if (imageKey != null) {
|
||||
this.imagePresent = Boolean.TRUE;
|
||||
} else {
|
||||
this.imagePresent = null;
|
||||
}
|
||||
this.allowedOffices = allowedOffices;
|
||||
this.changes = changes;
|
||||
this.currentChange = currentChange;
|
||||
this.allChanges = allChanges;
|
||||
}
|
||||
|
||||
public String displayName() {
|
||||
@@ -145,4 +171,8 @@ final public class ClientData {
|
||||
public Long officeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
|
||||
public ClientData currentChange() {
|
||||
return this.currentChange;
|
||||
}
|
||||
}
|
||||
+20
-7
@@ -7,6 +7,7 @@ import java.util.Set;
|
||||
|
||||
import org.mifosng.platform.accounting.api.data.ChartOfAccountsData;
|
||||
import org.mifosng.platform.api.LoanScheduleData;
|
||||
import org.mifosng.platform.api.commands.ClientCommand;
|
||||
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
|
||||
import org.mifosng.platform.api.data.AppUserData;
|
||||
import org.mifosng.platform.api.data.AuthenticatedUserData;
|
||||
@@ -497,14 +498,15 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serializeClientDataToJson(final boolean prettyPrint,
|
||||
final Set<String> responseParameters,
|
||||
final Collection<ClientData> clients) {
|
||||
public String serializeClientCommandToJson(final ClientCommand command) {
|
||||
final Gson gsonDeserializer = helper
|
||||
.createGsonBuilderWithParameterExclusionSerializationStrategy(
|
||||
CLIENT_DATA_PARAMETERS, prettyPrint, responseParameters);
|
||||
return helper.serializedJsonFrom(gsonDeserializer,
|
||||
clients.toArray(new ClientData[clients.size()]));
|
||||
.createGsonBuilderWithParameterExclusionSerializationStrategy(new HashSet<String>(), false, new HashSet<String>());
|
||||
return helper.serializedJsonFrom(gsonDeserializer, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serializeClientDataToJson(final ClientData client) {
|
||||
return serializeClientDataToJson(false, new HashSet<String>(), client);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -515,6 +517,17 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
|
||||
CLIENT_DATA_PARAMETERS, prettyPrint, responseParameters);
|
||||
return helper.serializedJsonFrom(gsonDeserializer, client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serializeClientDataToJson(final boolean prettyPrint,
|
||||
final Set<String> responseParameters,
|
||||
final Collection<ClientData> clients) {
|
||||
final Gson gsonDeserializer = helper
|
||||
.createGsonBuilderWithParameterExclusionSerializationStrategy(
|
||||
CLIENT_DATA_PARAMETERS, prettyPrint, responseParameters);
|
||||
return helper.serializedJsonFrom(gsonDeserializer,
|
||||
clients.toArray(new ClientData[clients.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serializeClientAccountSummaryCollectionDataToJson(
|
||||
|
||||
+8
-1
@@ -28,6 +28,7 @@ import org.mifosng.platform.api.commands.SavingAccountCommand;
|
||||
import org.mifosng.platform.api.commands.SavingProductCommand;
|
||||
import org.mifosng.platform.api.commands.StaffCommand;
|
||||
import org.mifosng.platform.api.commands.UserCommand;
|
||||
import org.mifosng.platform.api.data.ClientData;
|
||||
|
||||
public interface PortfolioApiDataConversionService {
|
||||
|
||||
@@ -49,7 +50,13 @@ public interface PortfolioApiDataConversionService {
|
||||
|
||||
DepositProductCommand convertJsonToDepositProductCommand(Long resourceIdentifier, String json);
|
||||
|
||||
ClientCommand convertJsonToClientCommand(Long resourceIdentifier, String json, boolean makerCheckerApproval);
|
||||
ClientCommand convertApiRequestJsonToClientCommand(Long resourceIdentifier, String json);
|
||||
|
||||
ClientCommand convertInternalJsonFormatToClientCommand(Long resourceIdentifier, String json, boolean checkerApproved);
|
||||
|
||||
ClientData convertInternalJsonFormatToClientDataChange(Long clientId, String json);
|
||||
|
||||
ClientCommand detectChanges(Long resourceId, String baseJson, String workingJson);
|
||||
|
||||
GroupCommand convertJsonToGroupCommand(Long resourceIdentifier, String json);
|
||||
|
||||
|
||||
+133
-4
@@ -19,7 +19,6 @@ import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.BranchMoneyTransferCommand;
|
||||
import org.mifosng.platform.api.commands.LoanReassignmentCommand;
|
||||
import org.mifosng.platform.api.commands.ChargeCommand;
|
||||
import org.mifosng.platform.api.commands.ClientCommand;
|
||||
import org.mifosng.platform.api.commands.ClientIdentifierCommand;
|
||||
@@ -35,6 +34,7 @@ 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.LoanReassignmentCommand;
|
||||
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
|
||||
import org.mifosng.platform.api.commands.LoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.NoteCommand;
|
||||
@@ -46,6 +46,7 @@ import org.mifosng.platform.api.commands.SavingProductCommand;
|
||||
import org.mifosng.platform.api.commands.StaffCommand;
|
||||
import org.mifosng.platform.api.commands.UserCommand;
|
||||
import org.mifosng.platform.api.data.ApiParameterError;
|
||||
import org.mifosng.platform.api.data.ClientData;
|
||||
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
|
||||
import org.mifosng.platform.infrastructure.api.JsonParserHelper;
|
||||
import org.mifosng.platform.infrastructure.errorhandling.InvalidJsonException;
|
||||
@@ -376,7 +377,96 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientCommand convertJsonToClientCommand(final Long resourceIdentifier, final String json, final boolean makerCheckerApproval) {
|
||||
public ClientCommand detectChanges(final Long resourceIdentifier, final String baseJson, final String workingJson) {
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
|
||||
final Map<String, Object> workingVersion = gsonConverter.fromJson(workingJson, typeOfMap);
|
||||
|
||||
final Set<String> workingParameters = workingVersion.keySet();
|
||||
|
||||
final JsonParser parser = new JsonParser();
|
||||
final JsonElement baseElement = parser.parse(baseJson);
|
||||
final JsonElement workingElement = parser.parse(workingJson);
|
||||
|
||||
final JsonParserHelper helper = new JsonParserHelper();
|
||||
final Set<String> ignoreParameters = new HashSet<String>();
|
||||
final Set<String> parametersPassedInRequest = new HashSet<String>();
|
||||
|
||||
Long officeId = null;
|
||||
String externalId = null;
|
||||
String firstname = null;
|
||||
String lastname = null;
|
||||
String clientOrBusinessName = null;
|
||||
LocalDate joiningDate = null;
|
||||
|
||||
for (final String parameter : workingParameters) {
|
||||
|
||||
final String officeIdParameterName = "officeId";
|
||||
if (officeIdParameterName.equalsIgnoreCase(parameter)) {
|
||||
final Long baseOfficeId = helper.extractLongNamed(officeIdParameterName, baseElement, ignoreParameters);
|
||||
final Long workingOfficeId = helper.extractLongNamed(officeIdParameterName, workingElement, ignoreParameters);
|
||||
if (!workingOfficeId.equals(baseOfficeId)) {
|
||||
officeId = workingOfficeId;
|
||||
parametersPassedInRequest.add(officeIdParameterName);
|
||||
}
|
||||
}
|
||||
|
||||
final String externalIdParamName = "externalId";
|
||||
if (externalIdParamName.equalsIgnoreCase(parameter)) {
|
||||
final String baseExternalId = helper.extractStringNamed(externalIdParamName, baseElement, ignoreParameters);
|
||||
final String workingExternalId = helper.extractStringNamed(externalIdParamName, workingElement, ignoreParameters);
|
||||
if (!baseExternalId.equals(workingExternalId)) {
|
||||
externalId = workingExternalId;
|
||||
parametersPassedInRequest.add(externalIdParamName);
|
||||
}
|
||||
}
|
||||
|
||||
final String firstnameParamName = "firstname";
|
||||
if (firstnameParamName.equalsIgnoreCase(parameter)) {
|
||||
final String baseValue = helper.extractStringNamed(firstnameParamName, baseElement, ignoreParameters);
|
||||
final String workingCopyValue = helper.extractStringNamed(firstnameParamName, workingElement, ignoreParameters);
|
||||
if (!baseValue.equals(workingCopyValue)) {
|
||||
firstname = workingCopyValue;
|
||||
parametersPassedInRequest.add(firstnameParamName);
|
||||
}
|
||||
}
|
||||
|
||||
final String lastnameParamName = "lastname";
|
||||
if (lastnameParamName.equalsIgnoreCase(parameter)) {
|
||||
final String baseValue = helper.extractStringNamed(lastnameParamName, baseElement, ignoreParameters);
|
||||
final String workingCopyValue = helper.extractStringNamed(lastnameParamName, workingElement, ignoreParameters);
|
||||
if (!baseValue.equals(workingCopyValue)) {
|
||||
lastname = workingCopyValue;
|
||||
parametersPassedInRequest.add(lastnameParamName);
|
||||
}
|
||||
}
|
||||
|
||||
final String clientOrBusinessNameParamName = "clientOrBusinessName";
|
||||
if (clientOrBusinessNameParamName.equalsIgnoreCase(parameter)) {
|
||||
final String baseValue = helper.extractStringNamed(clientOrBusinessNameParamName, baseElement, ignoreParameters);
|
||||
final String workingCopyValue = helper.extractStringNamed(clientOrBusinessNameParamName, workingElement, ignoreParameters);
|
||||
if (!baseValue.equals(workingCopyValue)) {
|
||||
clientOrBusinessName = workingCopyValue;
|
||||
parametersPassedInRequest.add(clientOrBusinessNameParamName);
|
||||
}
|
||||
}
|
||||
|
||||
final String joinedDateParamName = "joinedDate";
|
||||
if (joinedDateParamName.equalsIgnoreCase(parameter)) {
|
||||
final LocalDate baseValue = helper.extractLocalDateAsArrayNamed(joinedDateParamName, baseElement, ignoreParameters);
|
||||
final LocalDate workingCopyValue = helper.extractLocalDateAsArrayNamed(joinedDateParamName, workingElement, ignoreParameters);
|
||||
if (!baseValue.isEqual(workingCopyValue)) {
|
||||
joiningDate = workingCopyValue;
|
||||
parametersPassedInRequest.add(joinedDateParamName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientCommand convertApiRequestJsonToClientCommand(final Long resourceIdentifier, final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
@@ -385,7 +475,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
final Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
final Set<String> supportedParams = new HashSet<String>(
|
||||
Arrays.asList("externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate", "locale", "dateFormat")
|
||||
Arrays.asList("id", "externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate", "locale", "dateFormat")
|
||||
);
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
@@ -402,7 +492,46 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
final String clientOrBusinessName = helper.extractStringNamed("clientOrBusinessName", element, parametersPassedInRequest);
|
||||
final LocalDate joiningDate = helper.extractLocalDateNamed("joiningDate", element, parametersPassedInRequest);
|
||||
|
||||
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, makerCheckerApproval);
|
||||
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientCommand convertInternalJsonFormatToClientCommand(final Long resourceIdentifier, final String json, final boolean checkerApproved) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
|
||||
final Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
final Set<String> supportedParams = new HashSet<String>(
|
||||
Arrays.asList("id", "externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate")
|
||||
);
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
|
||||
final JsonParser parser = new JsonParser();
|
||||
final JsonElement element = parser.parse(json);
|
||||
final JsonParserHelper helper = new JsonParserHelper();
|
||||
final Set<String> parametersPassedInRequest = new HashSet<String>();
|
||||
|
||||
final Long officeId = helper.extractLongNamed("officeId", element, parametersPassedInRequest);
|
||||
final String externalId = helper.extractStringNamed("externalId", element, parametersPassedInRequest);
|
||||
final String firstname = helper.extractStringNamed("firstname", element, parametersPassedInRequest);
|
||||
final String lastname = helper.extractStringNamed("lastname", element, parametersPassedInRequest);
|
||||
final String clientOrBusinessName = helper.extractStringNamed("clientOrBusinessName", element, parametersPassedInRequest);
|
||||
final LocalDate joiningDate = helper.extractLocalDateAsArrayNamed("joiningDate", element, parametersPassedInRequest);
|
||||
|
||||
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, checkerApproved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientData convertInternalJsonFormatToClientDataChange(final Long resourceIdentifier, final String json) {
|
||||
|
||||
final ClientCommand command = convertInternalJsonFormatToClientCommand(resourceIdentifier, json, false);
|
||||
|
||||
return ClientData.dataChangeInstance(resourceIdentifier, command.getOfficeId(), command.getExternalId(),
|
||||
command.getFirstname(), command.getLastname(), command.getClientOrBusinessName(), command.getJoiningDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
-3
@@ -5,6 +5,7 @@ import java.util.Set;
|
||||
|
||||
import org.mifosng.platform.accounting.api.data.ChartOfAccountsData;
|
||||
import org.mifosng.platform.api.LoanScheduleData;
|
||||
import org.mifosng.platform.api.commands.ClientCommand;
|
||||
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
|
||||
import org.mifosng.platform.api.data.AppUserData;
|
||||
import org.mifosng.platform.api.data.AuthenticatedUserData;
|
||||
@@ -91,10 +92,14 @@ public interface PortfolioApiJsonSerializerService {
|
||||
|
||||
String serializeDepositAccountDataToJson(boolean prettyPrint, Set<String> responseParameters, DepositAccountData account);
|
||||
|
||||
String serializeClientDataToJson(boolean prettyPrint, Set<String> responseParameters, Collection<ClientData> clients);
|
||||
|
||||
String serializeClientCommandToJson(ClientCommand command);
|
||||
|
||||
String serializeClientDataToJson(ClientData clientData);
|
||||
|
||||
String serializeClientDataToJson(boolean prettyPrint, Set<String> responseParameters, ClientData clientData);
|
||||
|
||||
|
||||
String serializeClientDataToJson(boolean prettyPrint, Set<String> responseParameters, Collection<ClientData> clients);
|
||||
|
||||
String serializeClientAccountSummaryCollectionDataToJson(boolean prettyPrint, Set<String> responseParameters, ClientAccountSummaryCollectionData clientAccount);
|
||||
|
||||
String serializeGroupAccountSummaryCollectionDataToJson(boolean prettyPrint, Set<String> responseParameters, GroupAccountSummaryCollectionData groupAccount);
|
||||
|
||||
+1
-1
@@ -157,7 +157,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
final String officeName = rs.getString("officeName");
|
||||
|
||||
return new ClientData(officeId, officeName, id, firstname,
|
||||
lastname, displayName, externalId, joinedDate,imageKey, null, null);
|
||||
lastname, displayName, externalId, joinedDate,imageKey, null, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+27
@@ -18,6 +18,7 @@ import org.mifosng.platform.api.data.ApiParameterError;
|
||||
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
|
||||
import org.springframework.format.number.NumberFormatter;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
@@ -176,6 +177,32 @@ public class JsonParserHelper {
|
||||
}
|
||||
return clientApplicationLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used with the local date is in array format
|
||||
*/
|
||||
public LocalDate extractLocalDateAsArrayNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInCommand) {
|
||||
LocalDate value = null;
|
||||
if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
|
||||
if (object.has(parameterName) && object.get(parameterName).isJsonArray()) {
|
||||
|
||||
parametersPassedInCommand.add(parameterName);
|
||||
|
||||
|
||||
final JsonArray dateArray = object.get(parameterName).getAsJsonArray();
|
||||
|
||||
Integer year = dateArray.get(0).getAsInt();
|
||||
Integer month = dateArray.get(1).getAsInt();
|
||||
Integer day = dateArray.get(2).getAsInt();
|
||||
|
||||
value = new LocalDate().withYearOfEra(year).withMonthOfYear(month).withDayOfMonth(day);
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public LocalDate extractLocalDateNamed(
|
||||
final String parameterName,
|
||||
|
||||
+5
-4
@@ -56,10 +56,9 @@ public class CommandSource extends AbstractPersistable<Long> {
|
||||
final String apiOperation,
|
||||
final String resource,
|
||||
final Long resourceId,
|
||||
final String jsonRequestBody,
|
||||
final AppUser maker,
|
||||
final LocalDate madeOnDate) {
|
||||
return new CommandSource(apiOperation, resource, resourceId, jsonRequestBody, maker, madeOnDate);
|
||||
return new CommandSource(apiOperation, resource, resourceId, maker, madeOnDate);
|
||||
}
|
||||
|
||||
protected CommandSource() {
|
||||
@@ -70,13 +69,11 @@ public class CommandSource extends AbstractPersistable<Long> {
|
||||
final String apiOperation,
|
||||
final String resource,
|
||||
final Long resourceId,
|
||||
final String jsonRequestBody,
|
||||
final AppUser maker,
|
||||
final LocalDate madeOnDate) {
|
||||
this.apiOperation = StringUtils.defaultIfEmpty(apiOperation, null);
|
||||
this.resource = StringUtils.defaultIfEmpty(resource, null);
|
||||
this.resourceId = resourceId;
|
||||
this.commandAsJson = StringUtils.defaultIfEmpty(jsonRequestBody, null);
|
||||
this.maker = maker;
|
||||
this.madeOnDate = madeOnDate.toDate();
|
||||
}
|
||||
@@ -90,6 +87,10 @@ public class CommandSource extends AbstractPersistable<Long> {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public void updateJsonTo(final String json) {
|
||||
this.commandAsJson = json;
|
||||
}
|
||||
|
||||
public Long resourceId() {
|
||||
return this.resourceId;
|
||||
}
|
||||
|
||||
+47
-24
@@ -2,8 +2,11 @@ package org.mifosng.platform.makerchecker.service;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosng.platform.api.commands.ClientCommand;
|
||||
import org.mifosng.platform.api.data.ClientData;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
|
||||
import org.mifosng.platform.client.service.ClientReadPlatformService;
|
||||
import org.mifosng.platform.client.service.ClientWritePlatformService;
|
||||
import org.mifosng.platform.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
|
||||
import org.mifosng.platform.makerchecker.domain.CommandSource;
|
||||
@@ -14,71 +17,91 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class PortfolioCommandSourceWriteServiceImpl implements PortfolioCommandSourceWritePlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final CommandSourceRepository commandSourceRepository;
|
||||
private final PortfolioApiDataConversionService apiDataConversionService;
|
||||
private final PortfolioApiJsonSerializerService apiJsonSerializerService;
|
||||
private final ClientWritePlatformService clientWritePlatformService;
|
||||
private final ClientReadPlatformService clientReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public PortfolioCommandSourceWriteServiceImpl(final PlatformSecurityContext context, final CommandSourceRepository makerCheckerRepository,
|
||||
final PortfolioApiDataConversionService apiDataConversionService,
|
||||
final ClientWritePlatformService clientWritePlatformService) {
|
||||
final PortfolioApiJsonSerializerService apiJsonSerializerService,
|
||||
final ClientWritePlatformService clientWritePlatformService,
|
||||
final ClientReadPlatformService clientReadPlatformService) {
|
||||
this.context = context;
|
||||
this.commandSourceRepository = makerCheckerRepository;
|
||||
this.apiDataConversionService = apiDataConversionService;
|
||||
this.apiJsonSerializerService = apiJsonSerializerService;
|
||||
this.clientWritePlatformService = clientWritePlatformService;
|
||||
this.clientReadPlatformService = clientReadPlatformService;
|
||||
}
|
||||
|
||||
// NOT TRANSACTIONAL BY DESIGN FOR NOW
|
||||
@Override
|
||||
public EntityIdentifier logCommandSource(final String taskOperation, final String taskEntity, final Long entityId, final String taskJson) {
|
||||
public EntityIdentifier logCommandSource(final String apiOperation, final String resource, final Long resourceId, final String jsonRequestBody) {
|
||||
|
||||
final AppUser maker = context.authenticatedUser();
|
||||
|
||||
final LocalDate asToday = new LocalDate();
|
||||
|
||||
final CommandSource entity = CommandSource.createdBy(taskOperation, taskEntity, entityId, taskJson, maker, asToday);
|
||||
final CommandSource commandSource = CommandSource.createdBy(apiOperation, resource, resourceId, maker, asToday);
|
||||
|
||||
final boolean makerCheckerApproval = false;
|
||||
Long resourceId = null;
|
||||
if (entity.isClientResource()) {
|
||||
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(entityId, entity.json(), makerCheckerApproval);
|
||||
if (entity.isCreate()) {
|
||||
Long newResourceId = null;
|
||||
if (commandSource.isClientResource()) {
|
||||
|
||||
// translate incoming api request json into java object catering for local and dateFormat parts of api
|
||||
final ClientCommand command = this.apiDataConversionService.convertApiRequestJsonToClientCommand(resourceId, jsonRequestBody);
|
||||
// produce serialized json of internal java object representation for persistence.
|
||||
final String internalCommandSerializedAsJson = this.apiJsonSerializerService.serializeClientCommandToJson(command);
|
||||
commandSource.updateJsonTo(internalCommandSerializedAsJson);
|
||||
|
||||
if (commandSource.isCreate()) {
|
||||
try {
|
||||
resourceId = this.clientWritePlatformService.createClient(command);
|
||||
entity.markAsChecked(maker, asToday);
|
||||
entity.updateResourceId(resourceId);
|
||||
newResourceId = this.clientWritePlatformService.createClient(command);
|
||||
commandSource.markAsChecked(maker, asToday);
|
||||
commandSource.updateResourceId(newResourceId);
|
||||
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
|
||||
// swallow this rollback transaction by design
|
||||
}
|
||||
} else if (entity.isUpdate()) {
|
||||
} else if (commandSource.isUpdate()) {
|
||||
try {
|
||||
EntityIdentifier result = this.clientWritePlatformService.updateClientDetails(command);
|
||||
resourceId = result.getEntityId();
|
||||
entity.markAsChecked(maker, asToday);
|
||||
// useful to employ change detection on update scenario to only store what details have changed
|
||||
final ClientData originalClient = this.clientReadPlatformService.retrieveIndividualClient(resourceId);
|
||||
final ClientData changedClient = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(resourceId, internalCommandSerializedAsJson);
|
||||
|
||||
final String baseJson = this.apiJsonSerializerService.serializeClientDataToJson(originalClient);
|
||||
final String workingJson = this.apiJsonSerializerService.serializeClientDataToJson(changedClient);
|
||||
final ClientCommand changesOnly = this.apiDataConversionService.detectChanges(resourceId, baseJson, workingJson);
|
||||
|
||||
final String changesOnlyJson = this.apiJsonSerializerService.serializeClientCommandToJson(changesOnly);
|
||||
commandSource.updateJsonTo(changesOnlyJson);
|
||||
|
||||
EntityIdentifier result = this.clientWritePlatformService.updateClientDetails(changesOnly);
|
||||
newResourceId = result.getEntityId();
|
||||
|
||||
commandSource.markAsChecked(maker, asToday);
|
||||
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
|
||||
// swallow this rollback transaction by design
|
||||
}
|
||||
} else if (entity.isDelete()) {
|
||||
} else if (commandSource.isDelete()) {
|
||||
try {
|
||||
EntityIdentifier result = this.clientWritePlatformService.deleteClient(command);
|
||||
resourceId = result.getEntityId();
|
||||
entity.markAsChecked(maker, asToday);
|
||||
newResourceId = result.getEntityId();
|
||||
commandSource.markAsChecked(maker, asToday);
|
||||
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
|
||||
// swallow this rollback transaction by design
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commandSourceRepository.save(entity);
|
||||
commandSourceRepository.save(commandSource);
|
||||
|
||||
return EntityIdentifier.makerChecker(resourceId, entity.getId());
|
||||
return EntityIdentifier.makerChecker(newResourceId, commandSource.getId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -92,7 +115,7 @@ public class PortfolioCommandSourceWriteServiceImpl implements PortfolioCommandS
|
||||
|
||||
Long resourceId = null;
|
||||
if (entity.isClientResource()) {
|
||||
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(entity.resourceId(), entity.json(), true);
|
||||
final ClientCommand command = this.apiDataConversionService.convertInternalJsonFormatToClientCommand(entity.resourceId(), entity.json(), true);
|
||||
if (entity.isCreate()) {
|
||||
resourceId = this.clientWritePlatformService.createClient(command);
|
||||
} else if (entity.isUpdate()) {
|
||||
|
||||
+2
@@ -10,4 +10,6 @@ public interface PortfolioCommandsReadPlatformService {
|
||||
|
||||
CommandSourceData retrieveById(Long id);
|
||||
|
||||
Collection<CommandSourceData> retrieveUnprocessChangesByResourceId(String apiResource, Long clientId);
|
||||
|
||||
}
|
||||
|
||||
+9
@@ -69,4 +69,13 @@ public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioComman
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {id});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CommandSourceData> retrieveUnprocessChangesByResourceId(final String apiResource, final Long resourceId) {
|
||||
|
||||
final CommandSourceMapper rm = new CommandSourceMapper();
|
||||
final String sql = "select " + rm.schema() + " where mc.api_resource like ? and mc.resource_id = ? and mc.checker_id is null order by mc.made_on_date DESC, mc.api_operation ASC";
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] {apiResource, resourceId});
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -12,6 +12,6 @@ public interface CodeWritePlatformService {
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'UPDATE_CODE)")
|
||||
Long updateCode(final CodeCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE', 'DELETE_CODE')")
|
||||
EntityIdentifier deleteCode(Long codeId);
|
||||
}
|
||||
Reference in New Issue
Block a user