Skip to content
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
2 changes: 2 additions & 0 deletions openmrs-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ dependencies {
def room_version = "2.1.0-alpha04"
def appcompat_version = "1.2.0-alpha01"
def material_version = "1.2.0-alpha03"
def worker_manager_version = "2.3.3"

implementation "androidx.work:work-runtime:$worker_manager_version"
implementation 'com.google.code.gson:gson:2.8.5'
implementation "androidx.appcompat:appcompat:$appcompat_version"
androidTestImplementation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ protected void onCreate(Bundle savedInstanceState) {
PlacesClient placesClient = Places.createClient(this);

// Create the mPresenter
mPresenter = new AddEditPatientPresenter(addEditPatientFragment, countries, patientID, placesClient);
mPresenter = new AddEditPatientPresenter(addEditPatientFragment, countries, patientID, placesClient, getApplicationContext());
}

@Override
Expand Down Expand Up @@ -146,4 +146,4 @@ protected void onPause() {
}
super.onPause();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.openmrs.mobile.activities.addeditpatient;

import android.content.Context;
import androidx.annotation.NonNull;

import com.google.android.libraries.places.api.net.PlacesClient;
Expand Down Expand Up @@ -44,7 +45,6 @@
public class AddEditPatientPresenter extends BasePresenter implements AddEditPatientContract.Presenter {

private final AddEditPatientContract.View mPatientInfoView;

private PatientRepository patientRepository;
private RestApi restApi;
private Patient mPatient;
Expand All @@ -56,12 +56,13 @@ public class AddEditPatientPresenter extends BasePresenter implements AddEditPat
public AddEditPatientPresenter(AddEditPatientContract.View mPatientInfoView,
List<String> countries,
String patientToUpdateId,
PlacesClient placesClient) {
PlacesClient placesClient,
Context appContext) {
this.mPatientInfoView = mPatientInfoView;
this.mPatientInfoView.setPresenter(this);
this.mCountries = countries;
this.patientToUpdateId = patientToUpdateId;
this.patientRepository = new PatientRepository();
this.patientRepository = new PatientRepository(appContext);
this.restApi = RestServiceBuilder.createService(RestApi.class);
this.placesClient = placesClient;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,27 @@

package org.openmrs.mobile.api.repository;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;
import org.jdeferred.android.AndroidDeferredManager;
import org.openmrs.mobile.api.EncounterService;
import org.openmrs.mobile.api.RestApi;
import org.openmrs.mobile.api.RestServiceBuilder;
import org.openmrs.mobile.api.workers.UpdateWorker;
import org.openmrs.mobile.api.promise.SimpleDeferredObject;
import org.openmrs.mobile.api.promise.SimplePromise;
import org.openmrs.mobile.application.OpenMRS;
import org.openmrs.mobile.application.OpenMRSLogger;
import org.openmrs.mobile.dao.PatientDAO;
import org.openmrs.mobile.databases.tables.PatientTable;
import org.openmrs.mobile.listeners.retrofit.DefaultResponseCallbackListener;
import org.openmrs.mobile.listeners.retrofit.DownloadPatientCallbackListener;
import org.openmrs.mobile.models.Encountercreate;
Expand Down Expand Up @@ -61,8 +69,18 @@ public class PatientRepository extends RetrofitRepository {
private PatientDAO patientDao;
private LocationRepository locationRepository;
private RestApi restApi;
private WorkManager mWorkManager = null;

public PatientRepository(){
//constructor specifically for update which uses a workManager Implementation
public PatientRepository(Context appContext) {
this.logger = new OpenMRSLogger();
this.patientDao = new PatientDAO();
this.locationRepository = new LocationRepository();
this.restApi = RestServiceBuilder.createService(RestApi.class);
this.mWorkManager = WorkManager.getInstance(appContext);
}

public PatientRepository() {
this.logger = new OpenMRSLogger();
this.patientDao = new PatientDAO();
this.locationRepository = new LocationRepository();
Expand Down Expand Up @@ -116,7 +134,7 @@ public void onResponse(@NonNull Call<PatientDto> call, @NonNull Response<Patient
uploadPatientPhoto(patient);

new PatientDAO().updatePatient(patient.getId(), patient);
if(!patient.getEncounters().equals(""))
if (!patient.getEncounters().equals(""))
addEncounters(patient);

deferred.resolve(patient);
Expand All @@ -126,7 +144,7 @@ public void onResponse(@NonNull Call<PatientDto> call, @NonNull Response<Patient
}

} else {
ToastUtil.error("Patient[" + patient.getId() + "] cannot be synced due to server error"+ response.message());
ToastUtil.error("Patient[" + patient.getId() + "] cannot be synced due to server error" + response.message());
deferred.reject(new RuntimeException("Patient cannot be synced due to server error: " + response.errorBody().toString()));
if (callbackListener != null) {
callbackListener.onErrorResponse(response.message());
Expand Down Expand Up @@ -166,12 +184,13 @@ private void uploadPatientPhoto(final Patient patient) {
public void onResponse(@NonNull Call<PatientPhoto> call, @NonNull Response<PatientPhoto> response) {
logger.i(response.message());
if (!response.isSuccessful()) {
ToastUtil.error("Patient photo cannot be synced due to server error: "+ response.message());
ToastUtil.error("Patient photo cannot be synced due to server error: " + response.message());
}
}

@Override
public void onFailure(@NonNull Call<PatientPhoto> call, @NonNull Throwable t) {
ToastUtil.notify("Patient photo cannot be synced due to error: " + t.toString() );
ToastUtil.notify("Patient photo cannot be synced due to error: " + t.toString());
}
});
}
Expand Down Expand Up @@ -232,6 +251,14 @@ public void onFailure(@NonNull Call<PatientDto> call, @NonNull Throwable t) {
}
});
} else {
//add patient to the local database
patientDao.updatePatient(patient.getId(), patient);

// enqueue the work to workManager
Data data = new Data.Builder().putString(PatientTable.Column.ID, patient.getId().toString()).build();
Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
mWorkManager.enqueue(new OneTimeWorkRequest.Builder(UpdateWorker.class).setConstraints(constraints).setInputData(data).build());

ToastUtil.notify("Sync is off. Patient Update data is saved locally " +
"and will sync when online mode is restored. ");
if (callbackListener != null) {
Expand All @@ -258,19 +285,19 @@ public void onResponse(@NonNull Call<PatientDto> call, @NonNull Response<Patient
}
});
callbackListener.onPatientDownloaded(newPatientDto.getPatient());
}
else {
} else {
callbackListener.onErrorResponse(response.message());
}
}

@Override
public void onFailure(@NonNull Call<PatientDto> call, @NonNull Throwable t) {
callbackListener.onErrorResponse(t.getMessage());
}
});
}
public SimplePromise<Bitmap> downloadPatientPhotoByUuid(String uuid) {

public SimplePromise<Bitmap> downloadPatientPhotoByUuid(String uuid) {
final SimpleDeferredObject<Bitmap> deferredObject = new SimpleDeferredObject<>();
Call<ResponseBody> call = restApi.downloadPatientPhoto(uuid);
call.enqueue(new Callback<ResponseBody>() {
Expand All @@ -291,6 +318,7 @@ public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<Respo
deferredObject.reject(throwable);
}
}

@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
deferredObject.reject(t);
Expand All @@ -300,17 +328,16 @@ public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
}

private void addEncounters(Patient patient) {
String enc=patient.getEncounters();
String enc = patient.getEncounters();
List<Long> list = new ArrayList<>();
for (String s : enc.split(","))
list.add(Long.parseLong(s));


for(long id:list)
{
for (long id : list) {
Encountercreate encountercreate = new Select()
.from(Encountercreate.class)
.where("id = ?",id)
.where("id = ?", id)
.executeSingle();
encountercreate.setPatient(patient.getUuid());
encountercreate.save();
Expand Down Expand Up @@ -350,7 +377,7 @@ private SimplePromise<IdentifierType> getPatientIdentifierTypeUuid() {
public void onResponse(@NonNull Call<Results<IdentifierType>> call, @NonNull Response<Results<IdentifierType>> response) {
Results<IdentifierType> idresList = response.body();
for (IdentifierType result : idresList.getResults()) {
if(result.getDisplay().equals("OpenMRS ID")) {
if (result.getDisplay().equals("OpenMRS ID")) {
deferred.resolve(result);
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/

package org.openmrs.mobile.api.workers;

import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import org.openmrs.mobile.R;
import org.openmrs.mobile.api.RestApi;
import org.openmrs.mobile.api.RestServiceBuilder;
import org.openmrs.mobile.application.OpenMRSLogger;
import org.openmrs.mobile.dao.PatientDAO;
import org.openmrs.mobile.databases.tables.PatientTable;
import org.openmrs.mobile.listeners.retrofit.DefaultResponseCallbackListener;
import org.openmrs.mobile.models.Patient;
import org.openmrs.mobile.models.PatientDto;
import org.openmrs.mobile.models.PatientPhoto;
import org.openmrs.mobile.utilities.NetworkUtils;
import org.openmrs.mobile.utilities.ToastUtil;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class UpdateWorker extends Worker {
private static final int ON_SUCCESS = 1;
private static final int ON_FAILURE = 2;
private static final int ON_UNSUCCESSFUL_RESPONSE_PHOTO_UPDATE = 3;
private static final int ON_FAILURE_RESPONSE_PHOTO_UPDATE = 4;

private RestApi restApi;
private OpenMRSLogger logger;
private Handler mHandler;

public UpdateWorker(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
super(appContext, workerParams);
restApi = RestServiceBuilder.createService(RestApi.class);
logger = new OpenMRSLogger();

mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
String responseMessage;
switch (msg.what) {
case ON_SUCCESS:
String updateSuccessPatientName = (String) msg.obj;
ToastUtil.success(Resources.getSystem().getString(R.string.patient_update_successful, updateSuccessPatientName));
break;
case ON_FAILURE:
String updateFailedPatientName = (String) msg.obj;
ToastUtil.error(Resources.getSystem().getString(R.string.patient_update_unsuccessful, updateFailedPatientName));
break;
case ON_UNSUCCESSFUL_RESPONSE_PHOTO_UPDATE:
responseMessage = (String) msg.obj;
ToastUtil.error(Resources.getSystem().getString(R.string.patient_photo_update_unsuccessful, responseMessage));
case ON_FAILURE_RESPONSE_PHOTO_UPDATE:
responseMessage = (String) msg.obj;
ToastUtil.notify(Resources.getSystem().getString(R.string.patient_photo_update_unsuccessful, responseMessage));
}
super.handleMessage(msg);
}
};
}


@NonNull
@Override
public Result doWork() {
final boolean[] result = new boolean[1];
String patientIdTobeUpdated = getInputData().getString(PatientTable.Column.ID);
PatientDAO patientDAO = new PatientDAO();
Patient patientTobeUpdated = patientDAO.findPatientByID(patientIdTobeUpdated);

updatePatient(patientTobeUpdated, new DefaultResponseCallbackListener() {
@Override
public void onResponse() {
result[0] = true;
Message msg = new Message();
msg.obj = patientTobeUpdated.getPerson().getName().getNameString();
msg.what = ON_SUCCESS;
mHandler.sendMessage(msg);
}

@Override
public void onErrorResponse(String errorMessage) {
result[0] = false;
Message msg = new Message();
msg.obj = patientTobeUpdated.getPerson().getName().getNameString();
msg.what = ON_FAILURE;
mHandler.sendMessage(msg);
}
});
return result[0] ? Result.success() : Result.retry();
}

public void updatePatient(final Patient patient, @Nullable final DefaultResponseCallbackListener callbackListener) {
PatientDto patientDto = patient.getPatientDto();
if (NetworkUtils.isOnline()) {
Call<PatientDto> call = restApi.updatePatient(patientDto, patient.getUuid(), "full");
call.enqueue(new Callback<PatientDto>() {
@Override
public void onResponse(@NonNull Call<PatientDto> call, @NonNull Response<PatientDto> response) {
if (response.isSuccessful()) {
PatientDto patientDto = response.body();
patient.setBirthdate(patientDto.getPerson().getBirthdate());

patient.setUuid(patient.getUuid());
if (patient.getPhoto() != null)
uploadPatientPhoto(patient);

new PatientDAO().updatePatient(patient.getId(), patient);

if (callbackListener != null) {
callbackListener.onResponse();
}
} else {
if (callbackListener != null) {
callbackListener.onErrorResponse(response.message());
}
}
}

@Override
public void onFailure(@NonNull Call<PatientDto> call, @NonNull Throwable t) {
if (callbackListener != null) {
callbackListener.onErrorResponse(t.getMessage());
}
}
});
}
}

private void uploadPatientPhoto(final Patient patient) {
PatientPhoto patientPhoto = new PatientPhoto();
patientPhoto.setPhoto(patient.getPhoto());
patientPhoto.setPerson(patient);
Call<PatientPhoto> personPhotoCall = restApi.uploadPatientPhoto(patient.getUuid(), patientPhoto);
personPhotoCall.enqueue(new Callback<PatientPhoto>() {
@Override
public void onResponse(@NonNull Call<PatientPhoto> call, @NonNull Response<PatientPhoto> response) {
logger.i(response.message());

if (!response.isSuccessful()) {
Message msg = new Message();
msg.obj = response.message();
msg.what = ON_UNSUCCESSFUL_RESPONSE_PHOTO_UPDATE;
mHandler.sendMessage(msg);
}
}

@Override
public void onFailure(@NonNull Call<PatientPhoto> call, @NonNull Throwable t) {
Message msg = new Message();
msg.obj = t.toString();
msg.what = ON_FAILURE_RESPONSE_PHOTO_UPDATE;
mHandler.sendMessage(msg);
}
});
}
}

Loading