Skip to content

Commit

Permalink
Merge branch 'master' into encrypt-file-example
Browse files Browse the repository at this point in the history
  • Loading branch information
hilpitome authored Sep 27, 2022
2 parents f31e371 + cc9dd87 commit aa650e8
Show file tree
Hide file tree
Showing 25 changed files with 662 additions and 81 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION_NAME=5.0.4-SNAPSHOT
VERSION_NAME=5.0.6-SNAPSHOT
VERSION_CODE=1
GROUP=org.smartregister
POM_SETTING_DESCRIPTION=OpenSRP Client Core Application
Expand Down
3 changes: 3 additions & 0 deletions opensrp-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ dependencies {
implementation 'de.hdodenhof:circleimageview:2.2.0'
implementation 'xerces:xercesImpl:2.12.0'

def work_version = "2.7.1"
implementation "androidx.work:work-runtime:$work_version"

// Add the dependency for the Performance Monitoring library
implementation 'com.google.firebase:firebase-perf:19.0.7'

Expand Down
12 changes: 12 additions & 0 deletions opensrp-core/src/main/java/org/smartregister/AllConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ public class AllConstants {

public static final String GPS = "gps";

public static final String IDENTIFIERS = "identifiers";


public static class Immunizations {
public static final String BCG = "bcg";
Expand Down Expand Up @@ -586,4 +588,14 @@ public interface SyncInfo {
String TASK_UNPROCESSED_EVENTS = "taskUnprocessedEvents";
String NULL_EVENT_SYNC_STATUS = "nullEventSyncStatus";
}

public static class EventType {
public static final String BITRH_REGISTRATION = "Birth Registration";
public static final String NEW_WOMAN_REGISTRATION = "New Woman Registration";
}

public static class Entity {
public static final String MOTHER = "mother";
}

}
10 changes: 10 additions & 0 deletions opensrp-core/src/main/java/org/smartregister/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.smartregister.repository.TaskRepository;
import org.smartregister.repository.TimelineEventRepository;
import org.smartregister.repository.UniqueIdRepository;
import org.smartregister.repository.ZeirIdCleanupRepository;
import org.smartregister.service.ANMService;
import org.smartregister.service.ActionService;
import org.smartregister.service.AlertService;
Expand Down Expand Up @@ -229,6 +230,7 @@ public class Context {
private ManifestRepository manifestRepository;
private ClientFormRepository clientFormRepository;
private ClientRelationshipRepository clientRelationshipRepository;
private ZeirIdCleanupRepository zeirIdCleanupRepository;

private static final String SHARED_PREFERENCES_FILENAME = "%s_preferences";

Expand Down Expand Up @@ -1252,5 +1254,13 @@ public ClientRelationshipRepository getClientRelationshipRepository() {
return clientRelationshipRepository;
}


public ZeirIdCleanupRepository zeirIdCleanupRepository() {
if (zeirIdCleanupRepository == null) {
zeirIdCleanupRepository = new ZeirIdCleanupRepository();
}
return zeirIdCleanupRepository;
}

///////////////////////////////////////////////////////////////////////////////
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.smartregister.cursoradapter;

import static android.os.Looper.getMainLooper;

import android.database.Cursor;
import android.os.Handler;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.ViewGroup;

import org.smartregister.commonregistry.CommonPersonObject;
import org.smartregister.commonregistry.CommonPersonObjectClient;
Expand Down Expand Up @@ -42,7 +46,10 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, Cursor cursor) {
if (listItemProvider.isFooterViewHolder(viewHolder)) {
listItemProvider.getFooterView(viewHolder, getCurrentPageCount(), getTotalPageCount(), hasNextPage(), hasPreviousPage());
// make sure counts are updated before updating the view
(new Handler(getMainLooper())).post(() -> {
listItemProvider.getFooterView(viewHolder, getCurrentPageCount(), getTotalPageCount(), hasNextPage(), hasPreviousPage());
});
} else {
CommonPersonObject personinlist = commonRepository.readAllcommonforCursorAdapter(cursor);
CommonPersonObjectClient pClient = new CommonPersonObjectClient(personinlist.getCaseId(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.smartregister.domain;

public enum DuplicateZeirIdStatus {
CLEANED("CLEANED"), PENDING("PENDING");
private String value;

DuplicateZeirIdStatus(String value) {
this.value = value;
}

public String value() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.smartregister.job;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

import org.smartregister.domain.DuplicateZeirIdStatus;
import org.smartregister.util.AppHealthUtils;

import timber.log.Timber;

public class DuplicateCleanerWorker extends Worker {
private Context mContext;

public DuplicateCleanerWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
mContext = context;
}

@NonNull
@Override
public Result doWork() {
DuplicateZeirIdStatus duplicateZeirIdStatus = AppHealthUtils.cleanUniqueZeirIds();
Timber.i("Doing some cleaning work");
if (duplicateZeirIdStatus != null && duplicateZeirIdStatus.equals(DuplicateZeirIdStatus.CLEANED))
WorkManager.getInstance(mContext).cancelWorkById(this.getId());

return Result.success();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

package org.smartregister.repository;

import static org.smartregister.AllConstants.ROWID;

import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Pair;
Expand All @@ -23,19 +26,24 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.smartregister.AllConstants;
import org.smartregister.Context;
import org.smartregister.CoreLibrary;
import org.smartregister.clientandeventmodel.DateUtil;
import org.smartregister.domain.Client;
import org.smartregister.domain.ClientRelationship;
import org.smartregister.domain.DuplicateZeirIdStatus;
import org.smartregister.domain.Event;
import org.smartregister.domain.UniqueId;
import org.smartregister.domain.db.Column;
import org.smartregister.domain.db.ColumnAttribute;
import org.smartregister.domain.db.EventClient;
import org.smartregister.p2p.sync.data.JsonData;
import org.smartregister.sync.intent.P2pProcessRecordsService;
import org.smartregister.sync.intent.PullUniqueIdsIntentService;
import org.smartregister.util.DatabaseMigrationUtils;
import org.smartregister.util.JsonFormUtils;
import org.smartregister.util.Utils;
import org.smartregister.view.activity.DrishtiApplication;

import java.lang.reflect.Type;
import java.text.ParseException;
Expand All @@ -52,8 +60,6 @@

import timber.log.Timber;

import static org.smartregister.AllConstants.ROWID;

/**
* Created by keyman on 27/07/2017.
*/
Expand All @@ -65,6 +71,10 @@ public class EventClientRepository extends BaseRepository {

public static final String VARCHAR = "VARCHAR";

public static final String ZEIR_ID = "ZEIR_ID";

public static final String M_ZEIR_ID = "M_ZEIR_ID";

protected Table clientTable;
protected Table eventTable;

Expand Down Expand Up @@ -354,12 +364,13 @@ public Boolean checkIfExistsByFormSubmissionId(Table table, String
return false;
}

private boolean populateStatement(SQLiteStatement statement, Table table, JSONObject
jsonObject, Map<String, Integer> columnOrder) {
private boolean populateStatement(SQLiteStatement statement, Table table, JSONObject jsonObject, Map<String, Integer> columnOrder) {
if (statement == null)
return false;

statement.clearBindings();
List columns;

try {
if (table.equals(clientTable)) {
columns = Arrays.asList(client_column.values());
Expand All @@ -373,10 +384,24 @@ private boolean populateStatement(SQLiteStatement statement, Table table, JSONOb

List<? extends Column> otherColumns = new ArrayList(columns);
if (!otherColumns.isEmpty()) {
otherColumns.removeAll(Arrays.asList(client_column.json, client_column.updatedAt, client_column.syncStatus, client_column.validationStatus, client_column.baseEntityId,
client_column.residence, client_column.locationId, client_column.clientType,
event_column.json, event_column.updatedAt, event_column.syncStatus, event_column.validationStatus, event_column.baseEntityId, event_column.eventId
, event_column.planId, event_column.taskId));
otherColumns.removeAll(Arrays.asList(
client_column.json,
client_column.updatedAt,
client_column.syncStatus,
client_column.validationStatus,
client_column.baseEntityId,
client_column.residence,
client_column.locationId,
client_column.clientType,
event_column.json,
event_column.updatedAt,
event_column.syncStatus,
event_column.validationStatus,
event_column.baseEntityId,
event_column.eventId,
event_column.planId,
event_column.taskId
));
}

for (Column column : otherColumns) {
Expand Down Expand Up @@ -2142,32 +2167,39 @@ public void markEventAsTaskUnprocessed(String formSubmissionId) {
}
}

public void markEventsAsSynced(Map<String, Object> syncedEventsClients) {
markEventsAsSynced(syncedEventsClients, null, null);
}

@SuppressWarnings("unchecked")
public void markEventsAsSynced(Map<String, Object> syncedEvents) {
public void markEventsAsSynced(Map<String, Object> syncedEventsClients, Set<String> failedEvents, Set<String> failedClients) {
try {
List<JSONObject> clients =
syncedEvents.containsKey(AllConstants.KEY.CLIENTS) ? (List<JSONObject>) syncedEvents.get(
AllConstants.KEY.CLIENTS) : null;
List<JSONObject> events =
syncedEvents.containsKey(AllConstants.KEY.EVENTS) ? (List<JSONObject>) syncedEvents.get(
AllConstants.KEY.EVENTS) : null;
List<JSONObject> clients = syncedEventsClients.containsKey(AllConstants.KEY.CLIENTS)
? (List<JSONObject>) syncedEventsClients.get(AllConstants.KEY.CLIENTS)
: null;

List<JSONObject> events = syncedEventsClients.containsKey(AllConstants.KEY.EVENTS)
? (List<JSONObject>) syncedEventsClients.get(AllConstants.KEY.EVENTS)
: null;

if (clients != null && !clients.isEmpty()) {
for (JSONObject client : clients) {
String baseEntityId = client.getString(client_column.baseEntityId.name());
markClientAsSynced(baseEntityId);
if (failedClients == null || !failedClients.contains(baseEntityId))
markClientAsSynced(baseEntityId);
}
}

if (events != null && !events.isEmpty()) {
for (JSONObject event : events) {
String formSubmissionId = event.getString(event_column.formSubmissionId.name());
markEventAsSynced(formSubmissionId);
if (failedEvents == null || !failedEvents.contains(formSubmissionId))
markEventAsSynced(formSubmissionId);
}
}
} catch (Exception e) {
Timber.e(e);
}

}

protected List<Client> fetchClients(String query, String[] params) {
Expand Down Expand Up @@ -2324,4 +2356,94 @@ public List<Event> getEventsByTaskIds(Set<String> taskIds) {
+ event_column.taskId.name()
+ " IN (" + StringUtils.repeat("?", ",", taskIds.size()) + ")", taskIds.toArray(new String[0]));
}

public DuplicateZeirIdStatus cleanDuplicateMotherIds() throws Exception {
String username = Context.getInstance().userService().getAllSharedPreferences().fetchRegisteredANM();

UniqueIdRepository uniqueIdRepository = Context.getInstance().getUniqueIdRepository();

Map<String, String> duplicates = Context.getInstance().zeirIdCleanupRepository().getClientsWithDuplicateZeirIds();
long unusedIdsCount = uniqueIdRepository.countUnUsedIds();

Timber.e("%d duplicates for provider: %s - %s", duplicates.size(), username, duplicates.toString());

if (duplicates.size() > 0) {
Timber.e(
"%s: %d duplicates for provider: %s - %s\nUnused Unique IDs: %d",
this.getClass().getSimpleName(),
duplicates.size(),
username,
duplicates,
unusedIdsCount
);
}

for (Map.Entry<String, String> duplicate : duplicates.entrySet()) {
String baseEntityId = duplicate.getKey();
String zeirId = duplicate.getValue();

JSONObject clientJson = getClientByBaseEntityId(baseEntityId);
JSONObject identifiers = clientJson.getJSONObject(AllConstants.IDENTIFIERS);

long unusedIds = uniqueIdRepository.countUnUsedIds();
if (unusedIds <= 30) { // Mske sure we have enough unused IDs left
Timber.e("%s: No more unique IDs available to assign to %s - %s; provider: %s", this.getClass().getSimpleName(), baseEntityId, zeirId, username);
android.content.Context applicationContext = CoreLibrary.getInstance().context().applicationContext();
applicationContext.startService(new Intent(applicationContext, PullUniqueIdsIntentService.class));
}

UniqueId uniqueId = uniqueIdRepository.getNextUniqueId();
String newZeirId = uniqueId != null ? uniqueId.getOpenmrsId() : null;

if (StringUtils.isBlank(newZeirId)) {
Timber.e("No unique ID found to assign to %s; provider: %s", baseEntityId, username);
return DuplicateZeirIdStatus.PENDING;
}

String eventType = AllConstants.EventType.BITRH_REGISTRATION;
String clientType = clientJson.getString(AllConstants.CLIENT_TYPE);

if (AllConstants.CHILD_TYPE.equals(clientType)) {
identifiers.put(ZEIR_ID, newZeirId.replaceAll("-", ""));
} else if (AllConstants.Entity.MOTHER.equals(clientType)) {
identifiers.put(M_ZEIR_ID, newZeirId);
eventType = AllConstants.EventType.NEW_WOMAN_REGISTRATION;
}
clientJson.put(AllConstants.IDENTIFIERS, identifiers);

// Add events to process this
addorUpdateClient(baseEntityId, clientJson);

// fetch the birth/new woman registration event
List<EventClient> registrationEvent = getEvents(
Collections.singletonList(baseEntityId),
Collections.singletonList(BaseRepository.TYPE_Synced),
Collections.singletonList(eventType)
);
Event event = null;
if (!registrationEvent.isEmpty())
event = registrationEvent.get(0).getEvent();

Client client = convert(clientJson, Client.class);

// reprocess the event
DrishtiApplication.getInstance().getClientProcessor().processClient(Collections.singletonList(new EventClient(event, client)));
markClientValidationStatus(baseEntityId, false);

uniqueIdRepository.close(newZeirId);

Timber.e("%s: %s - %s updated to %s; provider: %s", this.getClass().getSimpleName(), baseEntityId, zeirId, newZeirId, username);
}

if (duplicates.size() > 0) {
Timber.d("%s: Successfully processed %d duplicates for provider: %s - %s",
this.getClass().getSimpleName(),
duplicates.size(),
username,
duplicates
);
}
return DuplicateZeirIdStatus.CLEANED;
}

}
Loading

0 comments on commit aa650e8

Please sign in to comment.