diff --git a/gradle.properties b/gradle.properties index 42d4a6750f..cf3f664d41 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=1.2.2-SNAPSHOT +VERSION_NAME=1.2.3-SNAPSHOT VERSION_CODE=1 GROUP=org.smartregister POM_SETTING_DESCRIPTION=OpenSRP Client Chw Core Library diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/contract/ChwNotificationDetailsContract.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/contract/ChwNotificationDetailsContract.java index 16a8cd88cc..37aa6bbf08 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/contract/ChwNotificationDetailsContract.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/contract/ChwNotificationDetailsContract.java @@ -44,13 +44,6 @@ interface Interactor { */ void fetchNotificationDetails(String notificationId, String notificationType); - /** - * Crete a referral dismissal entry for the provided task id - * - * @param referralTaskId referral task id - */ - void createReferralDismissalEvent(String referralTaskId); - /** * Crete a Notification dismissal entry for the provided notification id * diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/dao/ChwNotificationDao.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/dao/ChwNotificationDao.java index 3052ea1e36..843eddead7 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/dao/ChwNotificationDao.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/dao/ChwNotificationDao.java @@ -215,4 +215,48 @@ private static String formatVisitDate(String visitDate) { } return ""; } + + /** + *This method is used to get details of referral notification with the provided task id + * @param referralId unique identifier for the task + * @return a notification record with details for the referral + */ + public static NotificationRecord getNotYetDoneReferral(String referralId) { + String sql = String.format( + "/* Get details for not yet done referral */\n" + + "SELECT ec_family_member.first_name || ' ' || CASE ec_family_member.last_name\n" + + " WHEN NULL THEN ec_family_member.middle_name\n" + + " ELSE ec_family_member.last_name END full_name,\n" + + " ec_family_member.dob AS dob,\n" + + " ec_family.village_town AS village,\n" + + " event.dateCreated AS notification_date,\n" + + " ec_family_member.phone_number AS phone_number,\n" + + " ec_family_member.base_entity_id AS base_entity_id\n" + + "\n" + + "FROM task\n" + + " inner join ec_family_member on ec_family_member.base_entity_id = task.for\n" + + " inner join ec_not_yet_done_referral on ec_not_yet_done_referral.referral_task = task._id\n" + + " inner join event on ec_not_yet_done_referral.id = event.formSubmissionId\n" + + " inner join ec_family on ec_family.base_entity_id = ec_family_member.relational_id\n" + + "\n" + + "WHERE ec_family_member.is_closed = '0'\n" + + " AND ec_family_member.date_removed is null\n" + + " AND task.code = 'Referral'\n" + + " AND task._id = '%s' COLLATE NOCASE\n", referralId); + + return AbstractDao.readSingleValue(sql, mapReferralNotificationColumns()); + + } + + private static DataMap mapReferralNotificationColumns() { + return row -> { + NotificationRecord record = new NotificationRecord(getCursorValue(row, "base_entity_id")); + record.setClientName(getCursorValue(row, "full_name")); + record.setClientDateOfBirth(getCursorValue(row, "dob")); + record.setVillage(getCursorValue(row, "village")); + record.setNotificationDate(getCursorValue(row, "notification_date")); + record.setPhone(getCursorValue(row, "phone_number")); + return record; + }; + } } diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationItem.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationItem.java index 03ee836203..aa02af3b3d 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationItem.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationItem.java @@ -5,6 +5,7 @@ public class NotificationItem { private String title; private List details; + private String clientBaseEntityId; public NotificationItem(String title, List details) { this.title = title; @@ -18,4 +19,13 @@ public String getTitle() { public List getDetails() { return details; } + + public NotificationItem setClientBaseEntityId(String clientBaseEntityId) { + this.clientBaseEntityId = clientBaseEntityId; + return this; + } + + public String getClientBaseEntityId() { + return clientBaseEntityId; + } } diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationRecord.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationRecord.java index 16a1ac8ed8..1be7d44eda 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationRecord.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/domain/NotificationRecord.java @@ -4,14 +4,17 @@ public class NotificationRecord { private String clientBaseEntityId; private String clientName; - private String careGiverName; + private String clientDateOfBirth; + private String phone; private String village; + private String notificationDate; private String actionTaken; private String dangerSigns; private String diagnosis; private String results; private String visitDate; private String method; + private String careGiverName; public NotificationRecord(String clientBaseEntityId) { this.clientBaseEntityId = clientBaseEntityId; @@ -96,4 +99,28 @@ public String getMethod() { public void setMethod(String method) { this.method = method; } + + public String getClientDateOfBirth() { + return clientDateOfBirth; + } + + public void setClientDateOfBirth(String clientDateOfBirth) { + this.clientDateOfBirth = clientDateOfBirth; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getNotificationDate() { + return notificationDate; + } + + public void setNotificationDate(String notificationDate) { + this.notificationDate = notificationDate; + } } diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/BaseChwNotificationDetailsInteractor.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/BaseChwNotificationDetailsInteractor.java index 0bd71269c0..37818be0c2 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/BaseChwNotificationDetailsInteractor.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/BaseChwNotificationDetailsInteractor.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.content.Context; +import android.util.Pair; import org.jetbrains.annotations.NotNull; import org.json.JSONObject; @@ -19,12 +20,18 @@ import org.smartregister.clientandeventmodel.Event; import org.smartregister.clientandeventmodel.Obs; import org.smartregister.family.FamilyLibrary; +import org.smartregister.family.util.Utils; +import org.smartregister.opd.utils.OpdUtils; import org.smartregister.repository.AllSharedPreferences; import org.smartregister.sync.helper.ECSyncHelper; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import timber.log.Timber; @@ -34,68 +41,13 @@ public class BaseChwNotificationDetailsInteractor implements ChwNotificationDeta private ChwNotificationDetailsContract.Presenter presenter; private Context context; + private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); public BaseChwNotificationDetailsInteractor(ChwNotificationDetailsContract.Presenter presenter) { this.presenter = presenter; context = (Activity) presenter.getView(); } - @Override - public void createReferralDismissalEvent(String referralTaskId) { - try { - AllSharedPreferences sharedPreferences = CoreChwApplication.getInstance().getContext().allSharedPreferences(); - ECSyncHelper syncHelper = FamilyLibrary.getInstance().getEcSyncHelper(); - String userLocationId = sharedPreferences.fetchUserLocalityId(sharedPreferences.fetchRegisteredANM()); - Event baseEvent = (Event) new Event() - .withBaseEntityId(presenter.getClientBaseEntityId()) - .withEventDate(new Date()) - .withEventType(CoreConstants.EventType.REFERRAL_DISMISSAL) - .withFormSubmissionId(JsonFormUtils.generateRandomUUIDString()) - .withEntityType(CoreConstants.TABLE_NAME.REFERRAL_DISMISSAL) - .withProviderId(sharedPreferences.fetchRegisteredANM()) - .withLocationId(userLocationId) - .withTeamId(sharedPreferences.fetchDefaultTeamId(sharedPreferences.fetchRegisteredANM())) - .withTeam(sharedPreferences.fetchDefaultTeam(sharedPreferences.fetchRegisteredANM())) - .withDateCreated(new Date()); - - baseEvent.addObs((new Obs()) - .withFormSubmissionField(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK) - .withValue(referralTaskId) - .withFieldCode(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK) - .withFieldType(CoreConstants.FORMSUBMISSION_FIELD).withFieldDataType(CoreConstants.TEXT) - .withParentCode("").withHumanReadableValues(new ArrayList<>())); - - baseEvent.addObs((new Obs()) - .withFormSubmissionField(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.NOTIFICATION_DATE_CREATED) - .withValue(presenter.getNotificationDates().first) - .withFieldCode(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.NOTIFICATION_DATE_CREATED) - .withFieldType(CoreConstants.FORMSUBMISSION_FIELD).withFieldDataType(CoreConstants.DATE) - .withParentCode("").withHumanReadableValues(new ArrayList<>())); - - baseEvent.addObs((new Obs()) - .withFormSubmissionField(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.NOTIFICATION_DISMISSAL_DATE) - .withValue(presenter.getNotificationDates().second) - .withFieldCode(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.NOTIFICATION_DISMISSAL_DATE) - .withFieldType(CoreConstants.FORMSUBMISSION_FIELD).withFieldDataType(CoreConstants.DATE) - .withParentCode("").withHumanReadableValues(new ArrayList<>())); - - CoreJsonFormUtils.tagSyncMetadata(sharedPreferences, baseEvent); - - baseEvent.setLocationId(userLocationId); - - JSONObject eventJson = new JSONObject(JsonFormUtils.gson.toJson(baseEvent)); - syncHelper.addEvent(referralTaskId, eventJson); - long lastSyncTimeStamp = sharedPreferences.fetchLastUpdatedAtDate(0); - Date lastSyncDate = new Date(lastSyncTimeStamp); - List formSubmissionIds = new ArrayList<>(); - formSubmissionIds.add(baseEvent.getFormSubmissionId()); - CoreChwApplication.getInstance().getClientProcessorForJava().processClient(syncHelper.getEvents(formSubmissionIds)); - sharedPreferences.saveLastUpdatedAtDate(lastSyncDate.getTime()); - } catch (Exception e) { - Timber.e(e, "BaseReferralNotificationDetailsInteractor --> createReferralDismissalEvent"); - } - } - @Override public void createNotificationDismissalEvent(String notificationId, String notificationType) { Event baseEvent = ChwNotificationUtil.createNotificationDismissalBaseEvent(presenter.getClientBaseEntityId(), ChwNotificationUtil.getNotificationDismissalEventType(context, notificationType)); @@ -116,17 +68,18 @@ public void createNotificationDismissalEvent(String notificationId, String notif @Override public void fetchNotificationDetails(String notificationId, String notificationType) { NotificationItem notificationItem = null; - - if (notificationType.equals(context.getString(R.string.notification_type_sick_child_follow_up))) { + if (notificationType.equals(context.getString(R.string.notification_type_sick_child_follow_up))) notificationItem = getSickChildFollowUpDetails(notificationId); - } else if (notificationType.equals(context.getString(R.string.notification_type_pnc_danger_signs)) || - notificationType.equals(context.getString(R.string.notification_type_anc_danger_signs))) { + else if (notificationType.equals(context.getString(R.string.notification_type_pnc_danger_signs)) || + notificationType.equals(context.getString(R.string.notification_type_anc_danger_signs))) notificationItem = getAncPncOutcomeDetails(notificationId, notificationType); - } else if (notificationType.contains(context.getString(R.string.notification_type_malaria_follow_up))) { + else if (notificationType.contains(context.getString(R.string.notification_type_malaria_follow_up))) notificationItem = getMalariaFollowUpDetails(notificationId); - } else if (notificationType.contains(context.getString(R.string.notification_type_family_planning))) { + else if (notificationType.contains(context.getString(R.string.notification_type_family_planning))) notificationItem = getDetailsForFamilyPlanning(notificationId); - } + else if (notificationType.contains(context.getString(R.string.notification_type_not_yet_done_referrals))) + notificationItem = getDetailsForNotYetDoneReferral(notificationId); + presenter.onNotificationDetailsFetched(notificationItem); } @@ -176,4 +129,58 @@ private NotificationItem getDetailsForFamilyPlanning(String notificationId) { details.add(context.getString(R.string.notification_village, notificationRecord.getVillage())); return new NotificationItem(title, details); } + + @NotNull + private NotificationItem getDetailsForNotYetDoneReferral(String referralTaskId) { + NotificationRecord record = ChwNotificationDao.getNotYetDoneReferral(referralTaskId); + List details = setNotificationRecordDetails(record); + details.add(context.getString(R.string.notification_record_not_yet_done)); + String title = context.getString(R.string.successful_referral_notification_title, + record.getClientName(), getClientAge(record.getClientDateOfBirth())); + return new NotificationItem(title, details).setClientBaseEntityId(record.getClientBaseEntityId()); + } + + private List setNotificationRecordDetails(NotificationRecord record) { + presenter.setClientBaseEntityId(record.getClientBaseEntityId()); + + Pair notificationDatesPair = null; + String notificationDate = record.getNotificationDate(); + try { + notificationDate = dateFormat.format(dateFormat.parse(record.getNotificationDate())); + notificationDatesPair = Pair.create(notificationDate, getDismissalDate(dateFormat.format(new Date()))); + } catch (ParseException e) { + Timber.e(e, "Error Parsing date: %s", record.getNotificationDate()); + } + presenter.setNotificationDates(notificationDatesPair); + + List details = new ArrayList<>(); + details.add(context.getString(R.string.notification_phone, record.getPhone() != null ? record.getPhone() : context.getString(R.string.no_phone_provided))); + details.add(context.getString(R.string.referral_notification_closure_date, notificationDate)); + if (record.getVillage() != null) { + details.add(context.getString(R.string.notification_village, record.getVillage())); + } + return details; + } + /** + * This method is used to obtain the date when the referral will be dismissed from the updates + * register + * + * @param eventCreationDate date the referral was created + * @return new date returned after adding 3 to the provided date + */ + private String getDismissalDate(String eventCreationDate) { + + Calendar calendar = Calendar.getInstance(); + try { + calendar.setTime(dateFormat.parse(eventCreationDate)); + } catch (ParseException e) { + Timber.e(e); + } + calendar.add(Calendar.DAY_OF_MONTH, 3); + return dateFormat.format(calendar.getTime()); + } + private String getClientAge(String dobString) { + String translatedYearInitial = context.getResources().getString(R.string.abbrv_years); + return OpdUtils.getClientAge(Utils.getDuration(dobString), translatedYearInitial); + } } diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/NavigationInteractor.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/NavigationInteractor.java index 5c4604c346..eea5c1b019 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/NavigationInteractor.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/interactor/NavigationInteractor.java @@ -15,6 +15,7 @@ import static org.smartregister.chw.core.utils.QueryConstant.ANC_DANGER_SIGNS_OUTCOME_COUNT_QUERY; import static org.smartregister.chw.core.utils.QueryConstant.FAMILY_PLANNING_UPDATE_COUNT_QUERY; import static org.smartregister.chw.core.utils.QueryConstant.MALARIA_HF_FOLLOW_UP_COUNT_QUERY; +import static org.smartregister.chw.core.utils.QueryConstant.NOT_YET_DONE_REFERRAL_COUNT_QUERY; import static org.smartregister.chw.core.utils.QueryConstant.PNC_DANGER_SIGNS_OUTCOME_COUNT_QUERY; import static org.smartregister.chw.core.utils.QueryConstant.SICK_CHILD_FOLLOW_UP_COUNT_QUERY; @@ -256,9 +257,10 @@ private int getCount(String tableName) { case CoreConstants.TABLE_NAME.NOTIFICATION_UPDATE: String referralNotificationQuery = - String.format("SELECT SUM(c) FROM (\n %s UNION ALL\n %s UNION ALL\n %s UNION ALL\n %s UNION ALL\n %s)", + String.format("SELECT SUM(c) FROM (\n %s \nUNION ALL\n %s \nUNION ALL\n %s \nUNION ALL\n %s \nUNION ALL\n %s \nUNION ALL %s)", SICK_CHILD_FOLLOW_UP_COUNT_QUERY, ANC_DANGER_SIGNS_OUTCOME_COUNT_QUERY, - PNC_DANGER_SIGNS_OUTCOME_COUNT_QUERY, FAMILY_PLANNING_UPDATE_COUNT_QUERY, MALARIA_HF_FOLLOW_UP_COUNT_QUERY); + PNC_DANGER_SIGNS_OUTCOME_COUNT_QUERY, FAMILY_PLANNING_UPDATE_COUNT_QUERY, + MALARIA_HF_FOLLOW_UP_COUNT_QUERY, NOT_YET_DONE_REFERRAL_COUNT_QUERY); return NavigationDao.getQueryCount(referralNotificationQuery); default: diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/job/CloseExpiredReferralsServiceJob.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/job/CloseExpiredReferralsServiceJob.java new file mode 100644 index 0000000000..cb5f6e680f --- /dev/null +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/job/CloseExpiredReferralsServiceJob.java @@ -0,0 +1,27 @@ +package org.smartregister.chw.core.job; + +import android.content.Intent; + +import androidx.annotation.NonNull; + +import org.smartregister.AllConstants; +import org.smartregister.chw.core.sync.intent.CloseExpiredReferralsIntentService; +import org.smartregister.job.BaseJob; + +/** + * Created by cozej4 on 2020-02-08. + * + * @author cozej4 https://github.com/cozej4 + */ +public class CloseExpiredReferralsServiceJob extends BaseJob { + + public static final String TAG = "CloseExpiredReferralsServiceJob"; + + @NonNull + @Override + protected Result onRunJob(@NonNull Params params) { + Intent intent = new Intent(getApplicationContext(), CloseExpiredReferralsIntentService.class); + getApplicationContext().startService(intent); + return params != null && params.getExtras().getBoolean(AllConstants.INTENT_KEY.TO_RESCHEDULE, false) ? Result.RESCHEDULE : Result.SUCCESS; + } +} diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/provider/BaseChwNotificationQueryProvider.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/provider/BaseChwNotificationQueryProvider.java index 093cd9f0e1..4b59c64aa8 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/provider/BaseChwNotificationQueryProvider.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/provider/BaseChwNotificationQueryProvider.java @@ -11,6 +11,8 @@ import static org.smartregister.chw.core.utils.QueryConstant.FAMILY_PLANNING_UPDATE_MAIN_SELECT; import static org.smartregister.chw.core.utils.QueryConstant.MALARIA_FOLLOW_UP_MAIN_SELECT; import static org.smartregister.chw.core.utils.QueryConstant.MALARIA_HF_FOLLOW_UP_COUNT_QUERY; +import static org.smartregister.chw.core.utils.QueryConstant.NOT_YET_DONE_REFERRAL_MAIN_SELECT; +import static org.smartregister.chw.core.utils.QueryConstant.NOT_YET_DONE_REFERRAL_COUNT_QUERY; import static org.smartregister.chw.core.utils.QueryConstant.PNC_DANGER_SIGNS_OUTCOME_COUNT_QUERY; import static org.smartregister.chw.core.utils.QueryConstant.PNC_DANGER_SIGNS_OUTCOME_MAIN_SELECT; import static org.smartregister.chw.core.utils.QueryConstant.SICK_CHILD_FOLLOW_UP_COUNT_QUERY; @@ -43,7 +45,8 @@ public String[] countExecuteQueries() { ANC_DANGER_SIGNS_OUTCOME_COUNT_QUERY, PNC_DANGER_SIGNS_OUTCOME_COUNT_QUERY, FAMILY_PLANNING_UPDATE_COUNT_QUERY, - MALARIA_HF_FOLLOW_UP_COUNT_QUERY + MALARIA_HF_FOLLOW_UP_COUNT_QUERY, + NOT_YET_DONE_REFERRAL_COUNT_QUERY }; } @@ -56,8 +59,9 @@ public String[] countExecuteQueries() { */ @NonNull public String mainSelectWhereIDsIn() { - return String.format("%s UNION ALL %s UNION ALL %s UNION ALL %s UNION ALL %s", + return String.format("%s UNION ALL %s UNION ALL %s UNION ALL %s UNION ALL %s UNION ALL %s", SICK_CHILD_FOLLOW_UP_MAIN_SELECT, ANC_DANGER_SIGNS_OUTCOME_MAIN_SELECT, - PNC_DANGER_SIGNS_OUTCOME_MAIN_SELECT, FAMILY_PLANNING_UPDATE_MAIN_SELECT, MALARIA_FOLLOW_UP_MAIN_SELECT); + PNC_DANGER_SIGNS_OUTCOME_MAIN_SELECT, FAMILY_PLANNING_UPDATE_MAIN_SELECT, + MALARIA_FOLLOW_UP_MAIN_SELECT, NOT_YET_DONE_REFERRAL_MAIN_SELECT); } } diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/repository/ChwTaskRepository.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/repository/ChwTaskRepository.java index 3c58eefa27..ec5cae8efd 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/repository/ChwTaskRepository.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/repository/ChwTaskRepository.java @@ -2,6 +2,7 @@ import net.sqlcipher.Cursor; +import org.smartregister.chw.core.utils.ChwDBConstants; import org.smartregister.chw.core.utils.CoreConstants; import org.smartregister.cloudant.models.Event; import org.smartregister.domain.Task; @@ -11,8 +12,10 @@ import org.smartregister.repository.TaskRepository; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import timber.log.Timber; @@ -63,4 +66,26 @@ public Set getReferralTasksForClientByStatus(String planId, String forEnti return taskSet; } + public List> getReferredTaskEvents() { + List> tasksEvents = new ArrayList<>(); + try (Cursor cursor = getReadableDatabase().rawQuery( + String.format( + "SELECT * FROM %s LEFT JOIN %s ON %s.%s = %s.%s WHERE %s = ? ORDER BY %s DESC", + CoreConstants.TABLE_NAME.TASK, CoreConstants.TABLE_NAME.REFERRAL, CoreConstants.TABLE_NAME.TASK, ChwDBConstants.TaskTable.REASON_REFERENCE, CoreConstants.TABLE_NAME.REFERRAL, org.smartregister.family.util.DBConstants.KEY.BASE_ENTITY_ID, + ChwDBConstants.TaskTable.BUSINESS_STATUS, ChwDBConstants.TaskTable.START), + new String[]{CoreConstants.BUSINESS_STATUS.REFERRED})) { + while (cursor.moveToNext()) { + HashMap columns = new HashMap(); + int columnCount = cursor.getColumnCount(); + for (int i = 0; i < columnCount; i++) { + columns.put(cursor.getColumnName(i), cursor.getString(i)); + } + tasksEvents.add(columns); + } + } catch (Exception e) { + Timber.e(e); + } + return tasksEvents; + } + } diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/sync/intent/CloseExpiredReferralsIntentService.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/sync/intent/CloseExpiredReferralsIntentService.java new file mode 100644 index 0000000000..6438fd7d97 --- /dev/null +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/sync/intent/CloseExpiredReferralsIntentService.java @@ -0,0 +1,250 @@ +package org.smartregister.chw.core.sync.intent; + +import android.app.IntentService; +import android.content.Intent; + +import org.joda.time.DateTime; +import org.json.JSONObject; +import org.smartregister.chw.core.application.CoreChwApplication; +import org.smartregister.chw.core.repository.ChwTaskRepository; +import org.smartregister.chw.core.utils.ChwDBConstants; +import org.smartregister.chw.core.utils.CoreConstants; +import org.smartregister.chw.core.utils.CoreJsonFormUtils; +import org.smartregister.chw.core.utils.Utils; +import org.smartregister.chw.referral.util.DBConstants; +import org.smartregister.clientandeventmodel.Event; +import org.smartregister.clientandeventmodel.Obs; +import org.smartregister.domain.Task; +import org.smartregister.family.FamilyLibrary; +import org.smartregister.repository.AllSharedPreferences; +import org.smartregister.repository.BaseRepository; +import org.smartregister.sync.helper.ECSyncHelper; +import org.smartregister.util.JsonFormUtils; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import timber.log.Timber; + +import static org.smartregister.chw.core.utils.ChwDBConstants.TaskTable; +import static org.smartregister.chw.core.utils.CoreConstants.DB_CONSTANTS.ID; +import static org.smartregister.chw.core.utils.CoreConstants.TASKS_FOCUS; + +/** + * Created by cozej4 on 2020-02-08. + * + * @author cozej4 https://github.com/cozej4 + */ +public class CloseExpiredReferralsIntentService extends IntentService { + + private static final String TAG = CloseExpiredReferralsIntentService.class.getSimpleName(); + private final ChwTaskRepository taskRepository; + private AllSharedPreferences sharedPreferences; + private ECSyncHelper syncHelper; + + + public CloseExpiredReferralsIntentService() { + super(TAG); + taskRepository = (ChwTaskRepository) CoreChwApplication.getInstance() + .getTaskRepository(); + sharedPreferences = Utils.getAllSharedPreferences(); + syncHelper = FamilyLibrary.getInstance().getEcSyncHelper(); + + } + + @Override + protected void onHandleIntent(Intent intent) { + List> referredTasks = taskRepository.getReferredTaskEvents(); + + for (Map task : referredTasks) { + String appointmentDate = task.get(DBConstants.Key.REFERRAL_APPOINTMENT_DATE); + String startDate = task.get(TaskTable.START); + + String focus = task.get(ChwDBConstants.TaskTable.FOCUS); + if (focus != null && startDate != null) { + Calendar expiredCalendar = Calendar.getInstance(); + if (focus.equals(TASKS_FOCUS.ANC_DANGER_SIGNS) || focus.equals(TASKS_FOCUS.PNC_DANGER_SIGNS) || focus.equals(TASKS_FOCUS.SUSPECTED_MALARIA)) { + expiredCalendar.setTimeInMillis(Long.parseLong(startDate)); + expiredCalendar.add(Calendar.HOUR_OF_DAY, 24); + checkIfExpired(expiredCalendar, task); + } else if (focus.equals(TASKS_FOCUS.SICK_CHILD) || focus.equals(TASKS_FOCUS.FP_SIDE_EFFECTS)) { + Calendar referralNotYetDoneCalendar = Calendar.getInstance(); + referralNotYetDoneCalendar.setTimeInMillis(Long.parseLong(startDate)); + referralNotYetDoneCalendar.add(Calendar.DAY_OF_MONTH, 3); + + expiredCalendar.setTimeInMillis(Long.parseLong(startDate)); + expiredCalendar.add(Calendar.DAY_OF_MONTH, 7); + + boolean isExpired = checkIfExpired(expiredCalendar, task); + if (Objects.requireNonNull(task.get(TaskTable.STATUS)).equals(Task.TaskStatus.READY.name()) && !isExpired) { + checkIfNotYetDone(referralNotYetDoneCalendar, task); + } + } else if (focus.equals(TASKS_FOCUS.SUSPECTED_TB)) { + expiredCalendar.setTimeInMillis(new BigDecimal(appointmentDate).longValue()); + expiredCalendar.add(Calendar.DAY_OF_MONTH, 3); + + checkIfExpired(expiredCalendar, task); + } else { + if (appointmentDate != null && !appointmentDate.isEmpty()) { + expiredCalendar.setTimeInMillis(new BigDecimal(appointmentDate).longValue()); + } else { + expiredCalendar.setTimeInMillis(new BigDecimal(startDate).longValue()); + } + expiredCalendar.add(Calendar.DAY_OF_MONTH, 7); + + checkIfExpired(expiredCalendar, task); + + } + } + } + } + + public boolean checkIfExpired(Calendar expiredCalendar, Map taskEvent) { + if (Calendar.getInstance().getTime().after(expiredCalendar.getTime())) { + saveExpiredReferralEvent( + taskEvent.get(ChwDBConstants.TaskTable.FOR), + taskEvent.get(ChwDBConstants.TaskTable.LOCATION), + taskEvent.get(ID), + taskEvent.get(ChwDBConstants.TaskTable.STATUS), + taskEvent.get(ChwDBConstants.TaskTable.BUSINESS_STATUS) + ); + expireTask(taskEvent.get(ID), taskEvent.get(ChwDBConstants.TaskTable.FOR)); + return true; + } + return false; + } + + public boolean checkIfNotYetDone(Calendar referralNotYetDoneCalendar, Map taskEvent) { + if (Calendar.getInstance().getTime().after(referralNotYetDoneCalendar.getTime())) { + saveNotYetDoneReferralEvent( + taskEvent.get(ChwDBConstants.TaskTable.FOR), + taskEvent.get(ChwDBConstants.TaskTable.LOCATION), + taskEvent.get(ID), + taskEvent.get(ChwDBConstants.TaskTable.STATUS) + ); + referralNotYetDoneTask(taskEvent.get(ID), taskEvent.get(ChwDBConstants.TaskTable.FOR)); + return true; + } + return false; + } + + private void saveExpiredReferralEvent(String baseEntityId, String userLocationId, String referralTaskId, String taskStatus, String businessStatus) { + try { + + Event baseEvent = generateEvent(baseEntityId, userLocationId, referralTaskId, taskStatus); + baseEvent.setEventType(CoreConstants.EventType.EXPIRED_REFERRAL); + baseEvent.setEntityType((CoreConstants.TABLE_NAME.CLOSE_REFERRAL)); + + baseEvent.addObs((new Obs()) + .withFormSubmissionField(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK_PREVIOUS_BUSINESS_STATUS) + .withValue(businessStatus) + .withFieldCode(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK_PREVIOUS_BUSINESS_STATUS) + .withFieldType(CoreConstants.FORMSUBMISSION_FIELD).withFieldDataType(CoreConstants.TEXT).withParentCode("") + .withHumanReadableValues(new ArrayList<>())); + + CoreJsonFormUtils.tagSyncMetadata(sharedPreferences, baseEvent); + + baseEvent.setLocationId(userLocationId); //setting the location uuid of the referral initiator so that to allow the event to sync back to the chw app since it sync data by location. + syncEvents(baseEvent, referralTaskId); + } catch (Exception e) { + Timber.e(e, "CloseExpiredReferralsIntentService --> saveExpiredReferralEvent"); + } + } + + private void saveNotYetDoneReferralEvent(String baseEntityId, String userLocationId, String referralTaskId, String taskStatus) { + try { + Event baseEvent = generateEvent(baseEntityId, userLocationId, referralTaskId, taskStatus); + baseEvent.setEventType((CoreConstants.EventType.NOT_YET_DONE_REFERRAL)); + baseEvent.setEntityType((CoreConstants.TABLE_NAME.NOT_YET_DONE_REFERRAL)); + + CoreJsonFormUtils.tagSyncMetadata(sharedPreferences, baseEvent); + baseEvent.setLocationId(userLocationId); //setting the location uuid of the referral initiator so that to allow the event to sync back to the chw app since it sync data by location. + + syncEvents(baseEvent, referralTaskId); + } catch (Exception e) { + Timber.e(e, "CloseExpiredReferralsIntentService --> saveExpiredReferralEvent"); + } + } + + private void syncEvents(Event baseEvent, String referralTaskId) { + try { + JSONObject eventJson = new JSONObject(JsonFormUtils.gson.toJson(baseEvent)); + syncHelper.addEvent(referralTaskId, eventJson); + long lastSyncTimeStamp = sharedPreferences.fetchLastUpdatedAtDate(0); + Date lastSyncDate = new Date(lastSyncTimeStamp); + List formSubmissionIds = new ArrayList<>(); + formSubmissionIds.add(baseEvent.getFormSubmissionId()); + CoreChwApplication.getInstance().getClientProcessorForJava().processClient(syncHelper.getEvents(formSubmissionIds)); + sharedPreferences.saveLastUpdatedAtDate(lastSyncDate.getTime()); + } catch (Exception e) { + Timber.e(e, "CloseExpiredReferralsIntentService --> syncEvents"); + } + } + + private Event generateEvent(String baseEntityId, String userLocationId, String referralTaskId, String taskStatus) { + Event baseEvent = null; + try { + AllSharedPreferences sharedPreferences = org.smartregister.family.util.Utils.getAllSharedPreferences(); + baseEvent = (Event) new Event() + .withBaseEntityId(baseEntityId) + .withEventDate(new Date()) + .withFormSubmissionId(JsonFormUtils.generateRandomUUIDString()) + .withProviderId(sharedPreferences.fetchRegisteredANM()) + .withLocationId(userLocationId) + .withTeamId(sharedPreferences.fetchDefaultTeamId(sharedPreferences.fetchRegisteredANM())) + .withTeam(sharedPreferences.fetchDefaultTeam(sharedPreferences.fetchRegisteredANM())) + .withDateCreated(new Date()); + + baseEvent.addObs((new Obs()) + .withFormSubmissionField(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK) + .withValue(referralTaskId) + .withFieldCode(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK) + .withFieldType(CoreConstants.FORMSUBMISSION_FIELD).withFieldDataType(CoreConstants.TEXT) + .withParentCode("").withHumanReadableValues(new ArrayList<>())); + + baseEvent.addObs((new Obs()) + .withFormSubmissionField(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK_PREVIOUS_STATUS) + .withValue(taskStatus) + .withFieldCode(CoreConstants.FORM_CONSTANTS.FORM_SUBMISSION_FIELD.REFERRAL_TASK_PREVIOUS_STATUS) + .withFieldType(CoreConstants.FORMSUBMISSION_FIELD).withFieldDataType(CoreConstants.TEXT) + .withParentCode("") + .withHumanReadableValues(new ArrayList<>())); + + CoreJsonFormUtils.tagSyncMetadata(sharedPreferences, baseEvent); + //setting the location uuid of the referral initiator so that to allow the event to sync back to the chw app since it sync data by location. + baseEvent.setLocationId(userLocationId); + } catch (Exception e) { + Timber.e(e, "CloseExpiredReferralsIntentService --> saveExpiredReferralEvent"); + } + return baseEvent; + } + + private void expireTask(String taskId, String baseEntityId) { + Task updatedTask = updateCurrentTask(taskId, baseEntityId); + updatedTask.setStatus(Task.TaskStatus.FAILED); + updatedTask.setBusinessStatus(CoreConstants.BUSINESS_STATUS.EXPIRED); + CoreChwApplication.getInstance().getTaskRepository().addOrUpdate(updatedTask); + } + + private void referralNotYetDoneTask(String taskId, String baseEntityId) { + Task updatedTask = updateCurrentTask(taskId, baseEntityId); + updatedTask.setStatus(Task.TaskStatus.CANCELLED); + CoreChwApplication.getInstance().getTaskRepository().addOrUpdate(updatedTask); + } + + private Task updateCurrentTask(String taskId, String baseEntityId) { + Task currentTask = taskRepository.getTaskByIdentifier(taskId); + DateTime now = new DateTime(); + currentTask.setExecutionEndDate(now); + currentTask.setLastModified(now); + currentTask.setForEntity(baseEntityId); + currentTask.setSyncStatus(BaseRepository.TYPE_Unsynced); + currentTask.setLastModified(now); + return currentTask; + } +} diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/ChwDBConstants.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/ChwDBConstants.java index d4b889ad4b..ea42b9ac02 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/ChwDBConstants.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/ChwDBConstants.java @@ -32,5 +32,6 @@ interface TaskTable { String START = "start"; String FOCUS = "focus"; String REASON_REFERENCE = "reason_reference"; + String LOCATION = "location"; } } \ No newline at end of file diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/CoreConstants.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/CoreConstants.java index 43ab3e6070..24ebb7e08f 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/CoreConstants.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/CoreConstants.java @@ -129,6 +129,8 @@ public static final class EventType { public static final String ANC_HOME_VISIT_NOT_DONE_UNDO = "ANC Home Visit Not Done Undo"; public static final String UPDATE_ANC_REGISTRATION = "Update ANC Registration"; public static final String CLOSE_REFERRAL = "Close Referral"; + public static final String EXPIRED_REFERRAL = "Expired Referral"; + public static final String NOT_YET_DONE_REFERRAL = "Not Yet Done Referral"; public static final String PREGNANCY_OUTCOME = "Pregnancy Outcome"; public static final String PNC_REGISTRATION = "PNC Registration"; public static final String PNC_HOME_VISIT_NOT_DONE = "PNC Home Visit Not Done"; @@ -622,6 +624,7 @@ public static class TABLE_NAME { public static final String PNC_REFERRAL = "ec_pnc_referral"; public static final String FP_REFERRAL = "ec_fp_referral"; public static final String CLOSE_REFERRAL = "ec_close_referral"; + public static final String NOT_YET_DONE_REFERRAL = "ec_not_yet_done_referral"; public static final String SCHEDULE_SERVICE = "schedule_service"; public static final String MALARIA_REFERRAL = "ec_malaria_referral"; public static final String STOCK_USAGE_REPORT = "ec_stock_usage_report"; @@ -630,6 +633,7 @@ public static class TABLE_NAME { public static final String REFERRAL_DISMISSAL = "ec_referral_dismissal"; public static final String PNC_DANGER_SIGNS_OUTCOME = "ec_pnc_danger_signs_outcome"; public static final String MALARIA_FOLLOW_UP_HF = "ec_malaria_followup_hf"; + public static final String REFERRAL = "ec_referral"; public static final String FAMILY_PLANNING_UPDATE = "ec_family_planning_update"; public static final String NOTIFICATION_UPDATE = "notification_update"; public static final String INDEPENDENT_CLIENT = "ec_independent_client"; @@ -888,6 +892,10 @@ public static final class TASKS_FOCUS { public static final String PNC_DANGER_SIGNS = "PNC Danger Signs"; public static final String FP_SIDE_EFFECTS = "Family planning side effects"; public static final String SUSPECTED_MALARIA = "Suspected Malaria"; + public static final String SUSPECTED_HIV= "Suspected HIV"; + public static final String SUSPECTED_TB= "Suspected TB"; + public static final String SUSPECTED_GBV= "Suspected GBV"; + public static final String SUSPECTED_CHILD_GBV= "Suspected Child GBV"; } public static final class REGISTER_TYPE { diff --git a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/QueryConstant.java b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/QueryConstant.java index 616ee37d59..e187de079e 100644 --- a/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/QueryConstant.java +++ b/opensrp-chw-core/src/main/java/org/smartregister/chw/core/utils/QueryConstant.java @@ -41,6 +41,43 @@ public interface QueryConstant { " AND ec_family_member.base_entity_id IN (%s)\n" + "ORDER BY event.dateCreated DESC"; + String NOT_YET_DONE_REFERRAL_COUNT_QUERY = + "/* COUNT NOTIFICATION FROM NOT YET DONE REFERRALS FROM THE FACILITY */\n" + + "SELECT COUNT(*) AS c\n" + + "FROM task\n" + + " inner join ec_family_member on ec_family_member.base_entity_id = task.for\n" + + " inner join ec_not_yet_done_referral on ec_not_yet_done_referral.referral_task = task._id\n" + + " inner join event on ec_not_yet_done_referral.id = event.formSubmissionId\n" + + "\n" + + "WHERE ec_family_member.is_closed = '0'\n" + + " AND ec_family_member.date_removed is null\n" + + " AND task.status = 'CANCELLED'\n" + + " AND task.code = 'Referral'\n"; + + String NOT_YET_DONE_REFERRAL_MAIN_SELECT = + "/* NOTIFICATION FROM NOT YET DONE REFERRALS FROM THE FACILITY */\n" + + "SELECT ec_family_member.first_name AS first_name,\n" + + " ec_family_member.middle_name AS middle_name,\n" + + " ec_family_member.last_name AS last_name,\n" + + " ec_family_member.dob AS dob,\n" + + " ec_family_member.id AS _id,\n" + + " ec_family_member.relational_id AS relationalid,\n" + + " task._id AS referral_task_id,\n" + + " event.dateCreated AS notification_date,\n" + + " 'Referral not completed yet' AS notification_type\n" + + "\n" + + "FROM task\n" + + " inner join ec_family_member on ec_family_member.base_entity_id = task.for\n" + + " inner join ec_not_yet_done_referral on ec_not_yet_done_referral.referral_task = task._id\n" + + " inner join event on ec_not_yet_done_referral.id = event.formSubmissionId\n" + + "\n" + + "WHERE ec_family_member.is_closed = '0'\n" + + " AND ec_family_member.date_removed is null\n" + + " AND task.status = 'CANCELLED'\n" + + " AND task.code = 'Referral'\n" + + " AND ec_family_member.base_entity_id IN (%s)\n" + + "ORDER BY event.dateCreated DESC"; + String ALL_CLIENTS_SELECT_QUERY = "/* ANC REGISTER */\n" + "SELECT ec_family_member.first_name AS first_name,\n" + " ec_family_member.middle_name AS middle_name,\n" + diff --git a/opensrp-chw-core/src/main/res/values/strings.xml b/opensrp-chw-core/src/main/res/values/strings.xml index 5462760b83..a458de7499 100644 --- a/opensrp-chw-core/src/main/res/values/strings.xml +++ b/opensrp-chw-core/src/main/res/values/strings.xml @@ -633,6 +633,9 @@ Selected method: %1$s Record closed Household/Caregiver Phone: %1$s + Referral not yet done + No phone provided + Closure date: %1$s @@ -655,6 +658,7 @@ ANC Danger Signs Malaria Follow-up Family Planning + Referral not completed yet perform click action diff --git a/sample/src/main/java/org/smartregister/chw/hf/activity/FamilyOtherMemberProfileActivity.java b/sample/src/main/java/org/smartregister/chw/hf/activity/FamilyOtherMemberProfileActivity.java index e00393c179..bb9b59fea4 100644 --- a/sample/src/main/java/org/smartregister/chw/hf/activity/FamilyOtherMemberProfileActivity.java +++ b/sample/src/main/java/org/smartregister/chw/hf/activity/FamilyOtherMemberProfileActivity.java @@ -33,6 +33,7 @@ public class FamilyOtherMemberProfileActivity extends CoreFamilyOtherMemberProfi protected void onCreation() { super.onCreation(); baJsonFormUtils = new BAJsonFormUtils(HealthFacilityApplication.getInstance()); + setIndependentClient(false); } @Override @@ -67,6 +68,11 @@ protected void startMalariaFollowUpVisit() { //TODO implement start malaria follow-up visit for HF } + @Override + protected void setIndependentClient(boolean isIndependent) { + this.isIndependent = isIndependent; + } + @Override protected void removeIndividualProfile() { Timber.d("Remove member action is not required in HF");