Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Move to My Catchment Events Sync Without Location Filter #946

Merged
merged 21 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<artifactId>opensrp-server-web</artifactId>
<packaging>war</packaging>
<version>3.0.12-SNAPSHOT</version>
<version>3.0.13-SNAPSHOT</version>
<name>opensrp-server-web</name>
<description>OpenSRP Server Web Application</description>
<url>https://github.com/OpenSRP/opensrp-server-web</url>
Expand All @@ -25,7 +25,7 @@
<redis.lettuce.version>5.2.2.RELEASE</redis.lettuce.version>
<opensrp.updatePolicy>always</opensrp.updatePolicy>
<nexus-staging-maven-plugin.version>1.5.1</nexus-staging-maven-plugin.version>
<opensrp.core.version>3.0.8-SNAPSHOT</opensrp.core.version>
<opensrp.core.version>3.0.9-SNAPSHOT</opensrp.core.version>
<opensrp.connector.version>2.3.2-SNAPSHOT</opensrp.connector.version>
<opensrp.interface.version>2.0.1-SNAPSHOT</opensrp.interface.version>
<opensrp.common.version>2.0.3-SNAPSHOT</opensrp.common.version>
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/opensrp/web/GlobalExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package org.opensrp.web;

import static org.opensrp.web.Constants.DEFAULT_EXCEPTION_HANDLER_MESSAGE;

import java.net.ConnectException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensrp.web.dto.ResponseDto;
Expand All @@ -21,6 +17,10 @@
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.net.ConnectException;

import static org.opensrp.web.Constants.DEFAULT_EXCEPTION_HANDLER_MESSAGE;

@ControllerAdvice
public class GlobalExceptionHandler {

Expand Down
129 changes: 117 additions & 12 deletions src/main/java/org/opensrp/web/rest/EventResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;

import static org.opensrp.common.AllConstants.BaseEntity.BASE_ENTITY_ID;
Expand Down Expand Up @@ -139,8 +140,7 @@ protected ResponseEntity<String> sync(HttpServletRequest request) throws JsonPro

if (team != null || providerId != null || locationId != null || baseEntityId != null || teamId != null) {

EventSyncBean eventSyncBean = sync(providerId, locationId, baseEntityId, serverVersion, team, teamId, limit,
returnCount);
EventSyncBean eventSyncBean = sync(providerId, locationId, baseEntityId, serverVersion, team, teamId, limit, returnCount, false);

HttpHeaders headers = getJSONUTF8Headers();
if (returnCount) {
Expand Down Expand Up @@ -173,7 +173,8 @@ protected ResponseEntity<String> syncByPost(@RequestBody SyncParam syncParam) th
EventSyncBean eventSyncBean = sync(syncParam.getProviderId(), syncParam.getLocationId(),
syncParam.getBaseEntityId(), syncParam.getServerVersion(), syncParam.getTeam(),
syncParam.getTeamId(),
syncParam.getLimit(), syncParam.isReturnCount());
syncParam.getLimit(), syncParam.isReturnCount(),
false);

HttpHeaders headers = getJSONUTF8Headers();
if (syncParam.isReturnCount()) {
Expand All @@ -194,6 +195,72 @@ protected ResponseEntity<String> syncByPost(@RequestBody SyncParam syncParam) th
}
}

/**
* Fetch events without filtering by location
*
* @param request
* @return Events found matching the client IDs
* @throws JsonProcessingException
*/
@RequestMapping(value = "/sync-out-of-catchment", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
protected ResponseEntity<String> syncOutOfCatchment(HttpServletRequest request) throws JsonProcessingException {
EventSyncBean response = new EventSyncBean();

String providerId = getStringFilter(PROVIDER_ID, request);
String locationId = getStringFilter(LOCATION_ID, request);
String baseEntityId = getStringFilter(BASE_ENTITY_ID, request);
String serverVersion = getStringFilter(BaseEntity.SERVER_VERSIOIN, request);
String team = getStringFilter(TEAM, request);
String teamId = getStringFilter(TEAM_ID, request);
Integer limit = getIntegerFilter("limit", request);
boolean returnCount = Boolean.getBoolean(getStringFilter(RETURN_COUNT, request));

if (team != null || providerId != null || locationId != null || baseEntityId != null || teamId != null) {
EventSyncBean eventSyncBean = sync(providerId, locationId, baseEntityId, serverVersion, team, teamId, limit, returnCount, true);

HttpHeaders headers = getJSONUTF8Headers();
if (returnCount) {
headers.add(TOTAL_RECORDS, String.valueOf(eventSyncBean.getTotalRecords()));
}

return new ResponseEntity<>(objectMapper.writeValueAsString(eventSyncBean), headers, OK);
} else {
response.setMsg("Specify at least one filter");
return new ResponseEntity<>(objectMapper.writeValueAsString(response), BAD_REQUEST);
}
}

@RequestMapping(value = "/sync-out-of-catchment", method = POST, produces = { MediaType.APPLICATION_JSON_VALUE })
protected ResponseEntity<String> syncOutOfCatchmentByPost(@RequestBody SyncParam syncParam) throws JsonProcessingException {
EventSyncBean response = new EventSyncBean();

try {
if (syncParam.getTeam() != null || syncParam.getProviderId() != null || syncParam.getLocationId() != null
|| syncParam.getBaseEntityId() != null || syncParam.getTeamId() != null) {

EventSyncBean eventSyncBean = sync(syncParam.getProviderId(), syncParam.getLocationId(),
syncParam.getBaseEntityId(), syncParam.getServerVersion(), syncParam.getTeam(),
syncParam.getTeamId(), syncParam.getLimit(), syncParam.isReturnCount(),
true);

HttpHeaders headers = getJSONUTF8Headers();
if (syncParam.isReturnCount()) {
headers.add(TOTAL_RECORDS, String.valueOf(eventSyncBean.getTotalRecords()));
}

return new ResponseEntity<>(objectMapper.writeValueAsString(eventSyncBean), headers, OK);
} else {
response.setMsg("Specify at least one filter");
return new ResponseEntity<>(objectMapper.writeValueAsString(response), BAD_REQUEST);
}
}
catch (Exception e) {
response.setMsg("Error occurred");
logger.error("", e);
return new ResponseEntity<>(objectMapper.writeValueAsString(response), INTERNAL_SERVER_ERROR);
}
}

/**
* Fetch clients and associated events allongside family registration events for the family that
* they attached to for the list of base entity ids passed
Expand All @@ -217,7 +284,7 @@ public ResponseEntity<String> syncClientsAndEventsByBaseEntityIds(@RequestBody S

}.getType());
for (String baseEntityId : baseEntityIdsList) {
EventSyncBean eventSyncBean = sync(null, null, baseEntityId, "0", null, null, null, false);
EventSyncBean eventSyncBean = sync(null, null, baseEntityId, "0", null, null, null, false, false);
combinedEvents.addAll(eventSyncBean.getEvents());
combinedClients.addAll(eventSyncBean.getClients());
if (eventSyncBean != null && eventSyncBean.getClients() != null && !eventSyncBean.getClients().isEmpty()) {
Expand All @@ -227,7 +294,7 @@ public ResponseEntity<String> syncClientsAndEventsByBaseEntityIds(@RequestBody S
&& withFamilyEvents) {
List<String> clientRelationships = clients.get(0).getRelationships().get(Constants.FAMILY);
for (String familyRelationship : clientRelationships) {
EventSyncBean familyEvents = sync(null, null, familyRelationship, "0", null, null, null, false);
EventSyncBean familyEvents = sync(null, null, familyRelationship, "0", null, null, null, false, false);
combinedEvents.addAll(familyEvents.getEvents());
combinedClients.addAll(familyEvents.getClients());
}
Expand All @@ -249,7 +316,7 @@ public ResponseEntity<String> syncClientsAndEventsByBaseEntityIds(@RequestBody S
}

public EventSyncBean sync(String providerId, String locationId, String baseEntityId, String serverVersion, String team,
String teamId, Integer limit, boolean returnCount) {
String teamId, Integer limit, boolean returnCount, boolean isOutOfCatchment) {
Long lastSyncedServerVersion = null;
if (serverVersion != null) {
lastSyncedServerVersion = Long.parseLong(serverVersion) + 1;
Expand All @@ -263,16 +330,17 @@ public EventSyncBean sync(String providerId, String locationId, String baseEntit
eventSearchBean.setBaseEntityId(baseEntityId);
eventSearchBean.setServerVersion(lastSyncedServerVersion);

return getEventsAndClients(eventSearchBean, limit == null || limit == 0 ? 25 : limit, returnCount);

return getEventsAndClients(eventSearchBean, limit == null || limit == 0 ? 25 : limit, returnCount, isOutOfCatchment);
}

private EventSyncBean getEventsAndClients(EventSearchBean eventSearchBean, Integer limit, boolean returnCount) {
private EventSyncBean getEventsAndClients(EventSearchBean eventSearchBean, Integer limit, boolean returnCount, boolean isOutOfCatchment) {
List<Event> events = new ArrayList<Event>();
List<String> clientIds = new ArrayList<String>();
List<Client> clients = new ArrayList<Client>();
long startTime = System.currentTimeMillis();
events = eventService.findEvents(eventSearchBean, BaseEntity.SERVER_VERSIOIN, "asc", limit == null ? 25 : limit);

events = getEvents(eventSearchBean, limit, isOutOfCatchment);

Long totalRecords = 0l;
logger.info("fetching events took: " + (System.currentTimeMillis() - startTime));
if (!events.isEmpty()) {
Expand All @@ -284,7 +352,12 @@ private EventSyncBean getEventsAndClients(EventSearchBean eventSearchBean, Integ
}
for (int i = 0; i < clientIds.size(); i = i + CLIENTS_FETCH_BATCH_SIZE) {
int end = Math.min(i + CLIENTS_FETCH_BATCH_SIZE, clientIds.size());
clients.addAll(clientService.findByFieldValue(BASE_ENTITY_ID, clientIds.subList(i, end)));

if (isOutOfCatchment) {
clients.addAll(clientService.findByFieldValueOutOfCatchment(BASE_ENTITY_ID, clientIds.subList(i, end)));
} else {
clients.addAll(clientService.findByFieldValue(BASE_ENTITY_ID, clientIds.subList(i, end)));
}
}
logger.info("fetching clients took: " + (System.currentTimeMillis() - startTime));

Expand Down Expand Up @@ -316,6 +389,19 @@ private EventSyncBean getEventsAndClients(EventSearchBean eventSearchBean, Integ
return eventSyncBean;
}

private List<Event> getEvents(EventSearchBean eventSearchBean, Integer limit, boolean isOutOfCatchment) {
if (isOutOfCatchment) {
// fetch siblings
String[] baseEntityIds = eventSearchBean.getBaseEntityId().split(",");
List<String> relationships = getRelationships(baseEntityIds);
eventSearchBean.setBaseEntityId(eventSearchBean.getBaseEntityId() + "," + String.join(",", relationships));

return eventService.findOutOfCatchmentEvents(eventSearchBean, BaseEntity.SERVER_VERSIOIN, "asc", limit == null ? 25 : limit);
} else {
return eventService.findEvents(eventSearchBean, BaseEntity.SERVER_VERSIOIN, "asc", limit == null ? 25 : limit);
}
}

private void searchMissingClients(List<String> clientIds, List<Client> clients, long startTime) {
if (searchMissingClients) {

Expand Down Expand Up @@ -353,7 +439,7 @@ protected ResponseEntity<String> getAll(@RequestParam long serverVersion,
eventSearchBean.setServerVersion(serverVersion > 0 ? serverVersion + 1 : serverVersion);
eventSearchBean.setEventType(eventType);
return new ResponseEntity<>(
objectMapper.writeValueAsString(getEventsAndClients(eventSearchBean, limit == null ? 25 : limit, false)),
objectMapper.writeValueAsString(getEventsAndClients(eventSearchBean, limit == null ? 25 : limit, false, false)),
getJSONUTF8Headers(), OK);
}

Expand Down Expand Up @@ -403,15 +489,18 @@ public ResponseEntity<String> save(@RequestBody String data, Authentication auth
new TypeToken<ArrayList<Client>>() {

}.getType());

for (Client client : clients) {
clientService.addorUpdate(client);
}
}

if (syncData.has("events")) {
ArrayList<Event> events = gson.fromJson(Utils.getStringFromJSON(syncData, "events"),
new TypeToken<ArrayList<Event>>() {

}.getType());

for (Event event : events) {
event = eventService.processOutOfArea(event);
eventService.addorUpdateEvent(event, currentUser(authentication).getUsername());
Expand Down Expand Up @@ -706,4 +795,20 @@ private void generateCSV(ExportEventDataSummary exportEventDataSummary, String f
}
}

private List<String> getRelationships(String[] baseEntityIds) {
List<String> relations = new ArrayList<>();

for (String baseEntityId : baseEntityIds) {
List<Client> siblings = clientService.findGlobalByRelationship(baseEntityId);

siblings.stream().forEach(entry-> entry.getBaseEntityId());
relations.addAll(
siblings.stream()
.map(child -> child.getBaseEntityId())
.collect(Collectors.toList())
);
}

return relations;
}
}
4 changes: 2 additions & 2 deletions src/test/java/org/opensrp/web/rest/EventResourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,9 @@ public void testSyncClientsAndEventsByBaseEntityIds() throws Exception {
String jsonObjectPayload = "{\"baseEntityIds\":[\"5dd43b2e-a873-444b-b527-95c4b040a5bb\"],\"withFamilyEvents\":true}";

doReturn(expectedEventSyncBean).when(eventResource).sync(null, null, "5dd43b2e-a873-444b-b527-95c4b040a5bb", "0",
null, null, null, false);
null, null, null, false, false);
doReturn(expectedFamilyEventSyncBean).when(eventResource).sync(null, null, "cf5d5fef-f120-4eb3-ab29-ed4d437e30c4",
"0", null, null, null, false);
"0", null, null, null, false, false);

ResponseEntity<String> clientEventsResponseEntity = eventResource
.syncClientsAndEventsByBaseEntityIds(jsonObjectPayload);
Expand Down