From 1aedf09245bacc1689bf977ea5b85a286aa8bdc2 Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Fri, 24 May 2024 21:03:26 +0300 Subject: [PATCH 01/11] fix current gestational age calculation --- .../main/assets/config/profile-overview.yml | 6 ++--- .../fragment/ProfileOverviewFragment.java | 25 +++++++++++++++++++ .../anc/library/util/ConstantsUtils.java | 2 ++ .../smartregister/anc/library/util/Utils.java | 18 ++++++++++++- reference-app/build.gradle | 2 +- 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/opensrp-anc/src/main/assets/config/profile-overview.yml b/opensrp-anc/src/main/assets/config/profile-overview.yml index 2634781..9ecdf65 100644 --- a/opensrp-anc/src/main/assets/config/profile-overview.yml +++ b/opensrp-anc/src/main/assets/config/profile-overview.yml @@ -14,9 +14,9 @@ fields: --- sub_group: current_pregnancy fields: - - template: "{{profile_overview.overview_of_pregnancy.current_pregnancy.ga}}: {gest_age}" - relevance: "gest_age != ''" - isRedFont: "gest_age > 40" + - template: "{{profile_overview.overview_of_pregnancy.current_pregnancy.ga}}: {current_gest_age}" + relevance: "current_gest_age != ''" + isRedFont: "current_gest_age > 40" - template: "{{profile_overview.overview_of_pregnancy.current_pregnancy.edd}}: {edd}" relevance: "edd != ''" diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java index 385e654..2304633 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java @@ -10,6 +10,9 @@ import androidx.recyclerview.widget.RecyclerView; import org.jeasy.rules.api.Facts; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; import org.smartregister.anc.library.AncLibrary; import org.smartregister.anc.library.R; import org.smartregister.anc.library.activity.ProfileActivity; @@ -97,6 +100,28 @@ protected void onResumption() { fetchContactAndAlertStatus(); yamlConfigListGlobal = new ArrayList<>(); //This makes sure no data duplication happens Facts facts = presenter.getImmediatePreviousContact(clientDetails, baseEntityId, contactNo); + String usgEdd = facts.get("ultrasound_edd").toString(); + String lmpEdd = facts.get("lmp_edd").toString(); + String sfhEdd = facts.get("sfh_edd").toString(); + String eddDate = !usgEdd.isEmpty() && !usgEdd.equals("0")? + usgEdd: !lmpEdd.isEmpty() && !lmpEdd.equals("0")? lmpEdd: + sfhEdd; + + // Define the date format pattern from ConstantsUtils + String pattern = ConstantsUtils.OPENSRP_DATE_TIME_FORMAT; + + // Create a DateTimeFormatter with the pattern + DateTimeFormatter formatter = DateTimeFormat.forPattern(pattern); + + // Get the current date and time + DateTime now = new DateTime(); + + // Format the current date and time as a string + String todaysDateString = now.toString(formatter); + String currentGestAge = Utils.calculateGaBasedOnUltrasoundEdd(eddDate, todaysDateString); + +// String currentGestAge = updateGaAsOfTodaysDate(facts); + facts.put("current_gest_age", currentGestAge); Iterable ruleObjects = utils.loadRulesFiles(FilePathUtils.FileUtils.PROFILE_OVERVIEW); for (Object ruleObject : ruleObjects) { diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java index 3f37650..3fdec26 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java @@ -6,6 +6,8 @@ public abstract class ConstantsUtils { public static final String SQLITE_DATE_TIME_FORMAT = "yyyy-MM-dd"; + + public static final String OPENSRP_DATE_TIME_FORMAT = "dd-MM-yyyy"; public static final String CONTACT_DATE_FORMAT = "dd/MM/yyyy"; public static final String CONTACT_SUMMARY_DATE_FORMAT = "dd MMMM yyyy"; public static final String VIEW_CONFIGURATION_PREFIX = "ViewConfiguration_"; diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java index a47287b..2f6e6bf 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java @@ -82,6 +82,7 @@ import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -1291,7 +1292,22 @@ public static Calendar nextWeekday(Calendar date) { } } - public static void setVisitDate(Facts facts){ + public static void setVisitDate(Facts facts) { visitDate = facts.get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); } + + public static String calculateGaBasedOnUltrasoundEdd(String ultrasoundDateEddDateString, String manualEncounterDateString) { + if (ultrasoundDateEddDateString != null && manualEncounterDateString != null) { + DateTimeFormatter formatter = DateTimeFormat.forPattern(ConstantsUtils.OPENSRP_DATE_TIME_FORMAT); + LocalDate ultrasoundDateEddDate = LocalDate.parse(ultrasoundDateEddDateString, formatter); + LocalDate manualEncounterDate = LocalDate.parse(manualEncounterDateString, formatter); + Days interval = Days.daysBetween(manualEncounterDate, ultrasoundDateEddDate); + + long daysBetween = 280 - Math.abs(interval.getDays()); + long weeks = daysBetween / 7; + long days = daysBetween % 7; + return weeks + " weeks " + days + " days"; + } + return "0"; + } } \ No newline at end of file diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 6a96a3c..24a7e8b 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -26,7 +26,7 @@ jacoco { // This variables are used by the version code & name generators ext.versionMajor = 1 ext.versionMinor = 6 -ext.versionPatch = 19 +ext.versionPatch = 21 ext.versionClassifier = null ext.isSnapshot = false ext.minimumSdkVersion = androidMinSdkVersion From 023e8bbe118768dba2c0c187de15c235d067a483 Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Fri, 24 May 2024 21:04:02 +0300 Subject: [PATCH 02/11] apply formatter --- .../fragment/ProfileOverviewFragment.java | 1 + .../smartregister/anc/library/util/Utils.java | 34 +++++++++---------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java index 2304633..f07bc69 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java @@ -203,4 +203,5 @@ public void updateTask(Task task) { public void refreshTasksList(boolean refresh) { // Implement here } + } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java index 2f6e6bf..455be47 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java @@ -318,7 +318,7 @@ public static boolean hasPendingRequiredFields(JSONObject object) throws Excepti */ public static void finalizeForm(Activity context, HashMap womanDetails, boolean isRefferal) { try { - Log.d("TAG", "finalizeForm: "+womanDetails.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE)); + Log.d("TAG", "finalizeForm: " + womanDetails.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE)); Intent contactSummaryFinishIntent = new Intent(context, ContactSummaryFinishActivity.class); contactSummaryFinishIntent @@ -475,7 +475,7 @@ public static int getGestationAgeFromEDDate(String expectedDeliveryDate) { LocalDate date = SQLITE_DATE_DF.withOffsetParsed().parseLocalDate(expectedDeliveryDate); LocalDate lmpDate = date.minusWeeks(ConstantsUtils.DELIVERY_DATE_WEEKS); Weeks weeks; - if(visitDate != null){ + if (visitDate != null) { weeks = Weeks.weeksBetween(lmpDate, DateTimeFormat.forPattern("dd-MM-yyyy").withOffsetParsed() .parseLocalDate(visitDate)); } else weeks = Weeks.weeksBetween(lmpDate, LocalDate.now()); @@ -736,10 +736,10 @@ public static String getClientLastVisitDate(String entityId) { } } if (visitDates.size() == 0) return null; - String visitDate = visitDates.get(visitDates.size()-1); - String day = visitDate.substring(0,2); - String month = visitDate.substring(3,5); - String year = visitDate.substring(6,10); + String visitDate = visitDates.get(visitDates.size() - 1); + String day = visitDate.substring(0, 2); + String month = visitDate.substring(3, 5); + String year = visitDate.substring(6, 10); return year + "-" + month + "-" + day; } catch (JSONException e) { return null; @@ -759,6 +759,7 @@ public static String getActualEDD(String edd, String recordDate, String visitDat return null; } } + /** * Loads yaml files that contain rules for the profile displays * @@ -814,6 +815,7 @@ private void createAndPersistPartialContact(String baseEntityId, int contactNo, ANCFormUtils.persistPartial(baseEntityId, contact); } + /** * Returns the Contact Tasks Repository {@link ContactTasksRepository} * @@ -1057,8 +1059,6 @@ public static String returnTranslatedStringJoinedValue(String value) { } - - @Nullable public String getManifestVersion(Context context) { if (StringUtils.isNotBlank(CoreLibrary.getInstance().context().allSharedPreferences().fetchManifestVersion())) { @@ -1068,9 +1068,9 @@ public String getManifestVersion(Context context) { } } - public void createSavePdf(Context context, List yamlConfigList, Facts facts,String womanName) throws FileNotFoundException { + public void createSavePdf(Context context, List yamlConfigList, Facts facts, String womanName) throws FileNotFoundException { setVisitDate(facts); - String FILENAME = womanName+"_"+context.getResources().getString(R.string.contact_summary_data_file); + String FILENAME = womanName + "_" + context.getResources().getString(R.string.contact_summary_data_file); String filePath = getAppPath(context) + FILENAME; if ((new File(filePath)).exists()) { @@ -1082,7 +1082,7 @@ public void createSavePdf(Context context, List yamlConfigList, Fact Document layoutDocument = new Document(pdfDocument); - addTitle(layoutDocument, context.getResources().getString(R.string.contact_summary_data, getTodaysDate(),womanName)); + addTitle(layoutDocument, context.getResources().getString(R.string.contact_summary_data, getTodaysDate(), womanName)); for (YamlConfig yamlConfig : yamlConfigList) { @@ -1092,13 +1092,14 @@ public void createSavePdf(Context context, List yamlConfigList, Fact List fields = yamlConfig.getFields(); StringBuilder outputBuilder = new StringBuilder(); for (YamlConfigItem yamlConfigItem : fields) { - for (String key :facts.asMap().keySet()) { + for (String key : facts.asMap().keySet()) { String value = Utils.returnTranslatedStringJoinedValue(facts.get(key).toString()); if (StringUtils.isNotBlank(value)) { facts.put(key, value); } else { facts.put(key, ""); - }} + } + } if (yamlConfigItem.isMultiWidget() != null && yamlConfigItem.isMultiWidget()) { prefillInjectableFacts(facts, yamlConfigItem.getTemplate()); } @@ -1138,7 +1139,7 @@ private void addParagraph(Document layoutDocument, HorizontalAlignment horizonta } private final String getAppPath(Context context) { - File dir = new File(Environment.getExternalStorageDirectory()+ File.separator + context.getResources().getString(R.string.app_name) + File.separator); + File dir = new File(Environment.getExternalStorageDirectory() + File.separator + context.getResources().getString(R.string.app_name) + File.separator); if (!dir.exists()) { dir.mkdir(); } @@ -1168,12 +1169,11 @@ public static List getLocationTagsByTagName(String tagName) { } public static List getLocationsByParentId(String parentId) { - try{ + try { JSONObject valueObject = new JSONObject(parentId); parentId = valueObject.getString(VALUE); - } - catch (JSONException e){ + } catch (JSONException e) { e.printStackTrace(); } From 4ef8a481fc50dfcd7b056a412e3aa5bf43bfdec4 Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Tue, 11 Jun 2024 18:57:01 +0300 Subject: [PATCH 03/11] Add data_migration_is_dirty to ec_client via database migration Added asyncTask for Regenerating Contact Schedule --- .../src/main/assets/ec_client_fields.json | 7 ++ .../anc/library/activity/ProfileActivity.java | 6 +- .../fragment/ProfileContactsFragment.java | 88 +++++++++++++++---- .../repository/PreviousContactRepository.java | 13 ++- .../repository/RegisterQueryProvider.java | 1 + .../task/LoadContactSummaryDataTask.java | 32 ++++--- .../anc/library/util/ConstantsUtils.java | 3 + .../smartregister/anc/library/util/Utils.java | 2 + opensrp-anc/src/main/res/values/strings.xml | 1 + reference-app/build.gradle | 12 +-- reference-app/src/main/assets/app.properties | 3 +- .../anc/repository/AncRepository.java | 11 +++ 12 files changed, 135 insertions(+), 44 deletions(-) diff --git a/opensrp-anc/src/main/assets/ec_client_fields.json b/opensrp-anc/src/main/assets/ec_client_fields.json index f9ecca1..682eb4b 100644 --- a/opensrp-anc/src/main/assets/ec_client_fields.json +++ b/opensrp-anc/src/main/assets/ec_client_fields.json @@ -299,6 +299,13 @@ "json_mapping": { "field": "addresses.address2" } + }, + { + "column_name": "data_migration_is_dirty", + "type": "Client", + "json_mapping": { + "field": "attributes.data_migration_is_dirty" + } } ] } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java index 402b44f..a83199b 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java @@ -118,8 +118,10 @@ private void getButtonAlertStatus() { detailMap = (HashMap) getIntent().getSerializableExtra(ConstantsUtils.IntentKeyUtils.CLIENT_MAP); contactNo = String.valueOf(Utils.getTodayContact(detailMap.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT))); buttonAlertStatus = Utils.processContactDoneToday(detailMap.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE), - ConstantsUtils.AlertStatusUtils.ACTIVE.equals(detailMap.get(DBConstantsUtils.KeyUtils.CONTACT_STATUS)) ? - ConstantsUtils.AlertStatusUtils.IN_PROGRESS : ""); + ConstantsUtils.AlertStatusUtils.ACTIVE.equals(detailMap.get(DBConstantsUtils.KeyUtils.CONTACT_STATUS)) ? + ConstantsUtils.AlertStatusUtils.IN_PROGRESS : ""); + + } protected void updateTasksTabTitle() { diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java index c92b5e3..1dd032c 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java @@ -1,6 +1,9 @@ package org.smartregister.anc.library.fragment; +import android.content.ContentValues; +import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; @@ -17,6 +20,8 @@ import org.apache.commons.lang3.StringUtils; import org.jeasy.rules.api.Facts; +import org.json.JSONException; +import org.json.JSONObject; import org.smartregister.anc.library.AncLibrary; import org.smartregister.anc.library.R; import org.smartregister.anc.library.activity.PreviousContactsDetailsActivity; @@ -32,22 +37,28 @@ import org.smartregister.anc.library.model.PreviousContact; import org.smartregister.anc.library.model.Task; import org.smartregister.anc.library.presenter.ProfileFragmentPresenter; +import org.smartregister.anc.library.repository.PatientRepository; +import org.smartregister.anc.library.repository.RegisterQueryProvider; +import org.smartregister.anc.library.rule.ContactRule; import org.smartregister.anc.library.util.ANCJsonFormUtils; import org.smartregister.anc.library.util.AppExecutors; import org.smartregister.anc.library.util.ConstantsUtils; import org.smartregister.anc.library.util.DBConstantsUtils; import org.smartregister.anc.library.util.FilePathUtils; import org.smartregister.anc.library.util.Utils; +import org.smartregister.p2p.exceptions.AsyncTaskCancelledException; import org.smartregister.view.fragment.BaseProfileFragment; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Objects; import timber.log.Timber; @@ -108,7 +119,11 @@ protected void onCreation() { clientDetails = (HashMap) getActivity().getIntent().getSerializableExtra(ConstantsUtils.IntentKeyUtils.CLIENT_MAP); } + buttonAlertStatus = Utils.getButtonAlertStatus(clientDetails, getActivity(), true); + if(clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")){ + buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; + } } } @@ -184,6 +199,9 @@ private void populatePreviousContactMissingEssentials(HashMap cl private void setUpAlertStatusButton() { Utils.processButtonAlertStatus(getActivity(), dueButton, buttonAlertStatus); + if(buttonAlertStatus.buttonAlertStatus.equals(ConstantsUtils.AlertStatusUtils.REGENERATE)){ + dueButton.setOnClickListener(view -> new RegenerateContactSchedulesTask(clientDetails).execute()); + } } private void initializeLastContactDetails(HashMap clientDetails) { @@ -203,31 +221,18 @@ private void initializeLastContactDetails(HashMap clientDetails) } String displayContactDate = ""; - // Extract visit date from facts - String manualEncounterDate = (String) facts.asMap().get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); - - if (!TextUtils.isEmpty(manualEncounterDate)) { - // If there's a visit date, parse it and format for display + // If no visit date, try to get contact date + String contactDate = (String) facts.asMap().get(ConstantsUtils.CONTACT_DATE); + if (!TextUtils.isEmpty(contactDate)) { + // If contact date exists, parse and format for display try { - Date lastContactDate = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).parse(manualEncounterDate); + Date lastContactDate = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(contactDate); displayContactDate = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(lastContactDate); } catch (ParseException e) { // Handle parsing exceptions throw new RuntimeException(e); } - } else { - // If no visit date, try to get contact date - String contactDate = (String) facts.asMap().get(ConstantsUtils.CONTACT_DATE); - if (!TextUtils.isEmpty(contactDate)) { - // If contact date exists, parse and format for display - try { - Date lastContactDate = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(contactDate); - displayContactDate = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(lastContactDate); - } catch (ParseException e) { - // Handle parsing exceptions - throw new RuntimeException(e); - } - } + } if (lastContactDetails.isEmpty()) { @@ -421,4 +426,49 @@ public void onClick(View view) { } } + + public class RegenerateContactSchedulesTask extends AsyncTask { + HashMap details; + + RegenerateContactSchedulesTask(HashMap details){ + this.details = details; + } + @Override + protected String doInBackground(Void... voids) { + + boolean isFirst = TextUtils.equals("1", details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT)); + int gestationAge = details.containsKey(DBConstantsUtils.KeyUtils.EDD) && details.get(DBConstantsUtils.KeyUtils.EDD) != null ? Utils + .getGestationAgeFromEDDate(details.get(DBConstantsUtils.KeyUtils.EDD)) : 4; + ContactRule contactRule = new ContactRule(gestationAge, isFirst, baseEntityId); + + List integerList = AncLibrary.getInstance().getAncRulesEngineHelper() + .getContactVisitSchedule(contactRule, ConstantsUtils.RulesFileUtils.CONTACT_RULES); + +// int nextContactVisitWeeks = integerList.get(0); + + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put(ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, integerList); + AncLibrary.getInstance().getDetailsRepository().add(baseEntityId, ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, jsonObject.toString(), + Calendar.getInstance().getTimeInMillis()); + ContentValues contentValues = new ContentValues(); + contentValues.put(ConstantsUtils.DATA_MIGRATION_IS_DIRTY, "0"); + PatientRepository.updatePatient(baseEntityId, contentValues, DBConstantsUtils.RegisterTable.DEMOGRAPHIC); + return "success"; + } catch (JSONException e) { + Timber.e(e); + } + + return "failure"; + } + + @Override + protected void onPostExecute(String message){ + if(message.equals("success")){ + + } + } + + + } } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PreviousContactRepository.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PreviousContactRepository.java index fbbbeca..f9001ae 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PreviousContactRepository.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PreviousContactRepository.java @@ -327,11 +327,17 @@ public Facts getPreviousContactFacts(String baseEntityId, String contactNo, bool Facts previousContactFacts = new Facts(); try { SQLiteDatabase db = getReadableDatabase(); - if (StringUtils.isNotBlank(baseEntityId) && StringUtils.isNotBlank(contactNo)) { - selection = BASE_ENTITY_ID + " = ? AND " + CONTACT_NO + " = ?"; + if (StringUtils.isBlank(baseEntityId)) + throw new IllegalStateException("No Base Entity Id provided to PreviousContactRepository.getPreviousContactFacts("); + selection = BASE_ENTITY_ID + " = ? "; + selectionArgs = new String[]{baseEntityId, null}; + + if (StringUtils.isNotBlank(contactNo)) { + selection += "AND " + CONTACT_NO + " = ?"; selectionArgs = new String[]{baseEntityId, contactNo}; } + mCursor = db.query(TABLE_NAME, projectionArgs, selection, selectionArgs, KEY, null, orderBy, null); // mCursor = db.query(TABLE_NAME, projectionArgs, selection, selectionArgs, KEY, null, orderBy, "1"); @@ -402,6 +408,9 @@ public Facts getImmediatePreviousSchedule(String baseEntityId, String contactNo) try { SQLiteDatabase db = getWritableDatabase(); db.setMaximumSize(4 * 1024 * 1024); + if(StringUtils.isBlank(contactNo)) + throw new IllegalStateException("contactNo. not provided for " + + "PreviousContactRepository.getImmediatePreviousSchedule()"); if (StringUtils.isNotBlank(baseEntityId) && StringUtils.isNotBlank(contactNo)) { selection = BASE_ENTITY_ID + " = ? AND " + CONTACT_NO + " = ? AND " + KEY + " = " + "'" + ConstantsUtils.CONTACT_SCHEDULE + "'"; diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java index be18f50..f5e8f79 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java @@ -84,6 +84,7 @@ DBConstantsUtils.KeyUtils.DOB_UNKNOWN, getDetailsTable() + "." + DBConstantsUtil getDetailsTable() + "." + ConstantsUtils.SpinnerKeyConstants.VILLAGE ,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.INSURANCE, getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.VILLAGE,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.UBUDEHE_CATEGORY, getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.NATIONAL_ID,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.DOCUMENT_TYPE, + getDemographicTable()+ "." + ConstantsUtils.DATA_MIGRATION_IS_DIRTY, getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.PASSPORT_ID,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.OTHER_ID }; } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/task/LoadContactSummaryDataTask.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/task/LoadContactSummaryDataTask.java index 546fbec..0a28702 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/task/LoadContactSummaryDataTask.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/task/LoadContactSummaryDataTask.java @@ -81,22 +81,26 @@ protected void onPostExecute(Void result) { ((ContactSummaryFinishActivity) context).saveFinishMenuItem.setEnabled(true); } - String lstVisitDate=facts.get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); + try { + String lstVisitDate = facts.get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); // Log.d("DATE",lstVisitDate); // Toast.makeText(context.getApplicationContext(), "DATE IS"+lstVisitDate,Toast.LENGTH_LONG).show(); - SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MM-yyyy"); - Date date = null; - try { - date = inputFormat.parse(lstVisitDate); - } catch (ParseException e) { - throw new RuntimeException(e); - } - String formattedDate = Utils.DB_DF.format(date); - if (formattedDate != null && ((ContactSummaryFinishActivity) context).saveFinishMenuItem != null) { - PatientRepository.updateLastContactDate(baseEntityId, formattedDate); - ((ContactSummaryFinishActivity) context).saveFinishMenuItem.setEnabled(true); - - } + SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MM-yyyy"); + Date date = null; + try { + date = inputFormat.parse(lstVisitDate); + } catch (ParseException e) { + throw new RuntimeException(e); + } + String formattedDate = Utils.DB_DF.format(date); + if (formattedDate != null && ((ContactSummaryFinishActivity) context).saveFinishMenuItem != null) { + PatientRepository.updateLastContactDate(baseEntityId, formattedDate); + ((ContactSummaryFinishActivity) context).saveFinishMenuItem.setEnabled(true); + + } + } catch (Exception e){ + Timber.e(e); + } ContactSummaryFinishAdapter adapter = new ContactSummaryFinishAdapter(context, ((ContactSummaryFinishActivity) context).getYamlConfigList(), facts); adapter.notifyDataSetChanged(); diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java index 3fdec26..3d58411 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/ConstantsUtils.java @@ -12,6 +12,8 @@ public abstract class ConstantsUtils { public static final String CONTACT_SUMMARY_DATE_FORMAT = "dd MMMM yyyy"; public static final String VIEW_CONFIGURATION_PREFIX = "ViewConfiguration_"; public static final String FORM = "form"; + + public static final String DATA_MIGRATION_IS_DIRTY = "data_migration_is_dirty"; public static final String ACCORDION_INFO_TEXT = "accordion_info_text"; public static final String ACCORDION_INFO_TITLE = "accordion_info_title"; public static final String DISPLAY_BOTTOM_SECTION = "display_bottom_section"; @@ -217,6 +219,7 @@ public static final class AlertStatusUtils { public static final String EXPIRED = "expired"; public static final String TODAY = "today"; public static final String ACTIVE = "active"; + public static final String REGENERATE = "regenerate"; } public static final class PrescriptionUtils{ diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java index 455be47..86139e5 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java @@ -601,6 +601,8 @@ public static void processButtonAlertStatus(Context context, Button dueButton, T dueButton.setText(String.format(context.getString(R.string.contact_recorded_today_no_break), Utils.getTodayContact(String.valueOf(buttonAlertStatus.nextContact)))); break; + case ConstantsUtils.AlertStatusUtils.REGENERATE: + dueButton.setText(R.string.regenerate_contact_schedule); default: dueButton.setBackground(context.getResources().getDrawable(R.drawable.contact_due)); dueButton.setTextColor(context.getResources().getColor(R.color.vaccine_blue_bg_st)); diff --git a/opensrp-anc/src/main/res/values/strings.xml b/opensrp-anc/src/main/res/values/strings.xml index a257646..d5256db 100644 --- a/opensrp-anc/src/main/res/values/strings.xml +++ b/opensrp-anc/src/main/res/values/strings.xml @@ -476,5 +476,6 @@ RPR positive Expected deliveries Late visits + Regenerate Contact Schedule \ No newline at end of file diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 24a7e8b..91fcd07 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -26,7 +26,7 @@ jacoco { // This variables are used by the version code & name generators ext.versionMajor = 1 ext.versionMinor = 6 -ext.versionPatch = 21 +ext.versionPatch = 25 ext.versionClassifier = null ext.isSnapshot = false ext.minimumSdkVersion = androidMinSdkVersion @@ -153,7 +153,7 @@ android { buildConfigField "int", "OPENMRS_UNIQUE_ID_INITIAL_BATCH_SIZE", '250' buildConfigField "int", "OPENMRS_UNIQUE_ID_BATCH_SIZE", '100' buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '1' - buildConfigField "int", "DATABASE_VERSION", '3' + buildConfigField "int", "DATABASE_VERSION", '4' buildConfigField "long", "MAX_SERVER_TIME_DIFFERENCE", "1800000l" buildConfigField "boolean", "TIME_CHECK", "false" buildConfigField "int", "DATA_SYNC_DURATION_MINUTES", '15' @@ -167,12 +167,12 @@ android { debug { //resValue "string", 'opensrp_url', '"https://opensrp.ths.rw/opensrp/"' // resValue "string", 'opensrp_url', '"https://anc-opensrp.ths.rw/opensrp/"' - resValue "string", 'opensrp_url', '"https://ancopensrp-stage.ths.rw/"' - //resValue "string", 'opensrp_url', '"https://anc.labs.smartregister.org/opensrp/"' +// resValue "string", 'opensrp_url', '"https://ancopensrp-stage.ths.rw/"' + resValue "string", 'opensrp_url', '"https://anc.labs.smartregister.org/opensrp/"' buildConfigField "int", "OPENMRS_UNIQUE_ID_INITIAL_BATCH_SIZE", '250' buildConfigField "int", "OPENMRS_UNIQUE_ID_BATCH_SIZE", '100' - buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '1' - buildConfigField "int", "DATABASE_VERSION", '3' + buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '2' + buildConfigField "int", "DATABASE_VERSION", '4' buildConfigField "long", "MAX_SERVER_TIME_DIFFERENCE", "1800000l" buildConfigField "boolean", "TIME_CHECK", "false" buildConfigField "int", "DATA_SYNC_DURATION_MINUTES", '15' diff --git a/reference-app/src/main/assets/app.properties b/reference-app/src/main/assets/app.properties index ae159c3..5fdb8aa 100644 --- a/reference-app/src/main/assets/app.properties +++ b/reference-app/src/main/assets/app.properties @@ -8,4 +8,5 @@ language.switching.enabled=true #DEFAULT_COUNTRY_ID=a26ca9c8-1441-495a-83b6-bb5df7698996 DEFAULT_COUNTRY_ID=1eb36348-b745-438c-9d49-2c3da8e6f9c9 widget.value.translated=true -ignore.location.deletion = true \ No newline at end of file +ignore.location.deletion = true +feature.profile.images.disabled=true \ No newline at end of file diff --git a/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java b/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java index 95c9107..2fea2fa 100644 --- a/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java +++ b/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java @@ -72,6 +72,9 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { case 3: upgradeToVersion3(db); break; + case 4: + upgradeToVersion4(db); + break; default: break; } @@ -147,5 +150,13 @@ private void upgradeToVersion3(SQLiteDatabase db) { } } + private void upgradeToVersion4(SQLiteDatabase db) { + try { + db.execSQL("ALTER TABLE " + DBConstantsUtils.DEMOGRAPHIC_TABLE_NAME + " ADD COLUMN " + ConstantsUtils.DATA_MIGRATION_IS_DIRTY + " VARCHAR"); + } catch (Exception e) { + Timber.e("upgradeToVersion4 %s", e.getMessage()); + } + } + } From f44df5e6eac9d96e9db83a4d1d99a566f641ccbc Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Thu, 13 Jun 2024 11:56:40 +0300 Subject: [PATCH 04/11] update ec_mother_details table with next_visit_date --- .../fragment/ProfileContactsFragment.java | 19 +++++++++++++++---- reference-app/build.gradle | 8 ++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java index 1dd032c..c95d318 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java @@ -20,6 +20,7 @@ import org.apache.commons.lang3.StringUtils; import org.jeasy.rules.api.Facts; +import org.joda.time.LocalDate; import org.json.JSONException; import org.json.JSONObject; import org.smartregister.anc.library.AncLibrary; @@ -444,16 +445,26 @@ protected String doInBackground(Void... voids) { List integerList = AncLibrary.getInstance().getAncRulesEngineHelper() .getContactVisitSchedule(contactRule, ConstantsUtils.RulesFileUtils.CONTACT_RULES); -// int nextContactVisitWeeks = integerList.get(0); + int nextContactVisitWeeks = integerList.get(0); JSONObject jsonObject = new JSONObject(); try { jsonObject.put(ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, integerList); AncLibrary.getInstance().getDetailsRepository().add(baseEntityId, ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, jsonObject.toString(), Calendar.getInstance().getTimeInMillis()); - ContentValues contentValues = new ContentValues(); - contentValues.put(ConstantsUtils.DATA_MIGRATION_IS_DIRTY, "0"); - PatientRepository.updatePatient(baseEntityId, contentValues, DBConstantsUtils.RegisterTable.DEMOGRAPHIC); + + ContentValues ecClientsCv = new ContentValues(); + ContentValues ecMotherDetailsCv = new ContentValues(); + ecClientsCv.put(ConstantsUtils.DATA_MIGRATION_IS_DIRTY, "0"); + PatientRepository.updatePatient(baseEntityId, ecClientsCv, DBConstantsUtils.RegisterTable.DEMOGRAPHIC); + + LocalDate localDate = new LocalDate(details.get(DBConstantsUtils.KeyUtils.EDD)); + String nextContactVisitDate = + localDate.minusWeeks(ConstantsUtils.DELIVERY_DATE_WEEKS).plusWeeks(nextContactVisitWeeks).toString(); + ecMotherDetailsCv.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT_DATE, nextContactVisitDate); + + PatientRepository.updatePatient(baseEntityId, ecMotherDetailsCv, DBConstantsUtils.RegisterTable.DETAILS); + return "success"; } catch (JSONException e) { Timber.e(e); diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 91fcd07..099cef6 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -26,7 +26,7 @@ jacoco { // This variables are used by the version code & name generators ext.versionMajor = 1 ext.versionMinor = 6 -ext.versionPatch = 25 +ext.versionPatch = 27 ext.versionClassifier = null ext.isSnapshot = false ext.minimumSdkVersion = androidMinSdkVersion @@ -167,11 +167,11 @@ android { debug { //resValue "string", 'opensrp_url', '"https://opensrp.ths.rw/opensrp/"' // resValue "string", 'opensrp_url', '"https://anc-opensrp.ths.rw/opensrp/"' -// resValue "string", 'opensrp_url', '"https://ancopensrp-stage.ths.rw/"' - resValue "string", 'opensrp_url', '"https://anc.labs.smartregister.org/opensrp/"' + resValue "string", 'opensrp_url', '"https://ancopensrp-stage.ths.rw/"' +// resValue "string", 'opensrp_url', '"https://anc.labs.smartregister.org/opensrp/"' buildConfigField "int", "OPENMRS_UNIQUE_ID_INITIAL_BATCH_SIZE", '250' buildConfigField "int", "OPENMRS_UNIQUE_ID_BATCH_SIZE", '100' - buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '2' + buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '1' buildConfigField "int", "DATABASE_VERSION", '4' buildConfigField "long", "MAX_SERVER_TIME_DIFFERENCE", "1800000l" buildConfigField "boolean", "TIME_CHECK", "false" From 0dc868c96798ab8ff6dea3eb871fcf383f3780fb Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Tue, 18 Jun 2024 19:11:59 +0300 Subject: [PATCH 05/11] update contact visit event --- opensrp-anc/build.gradle | 2 + .../activity/BaseHomeRegisterActivity.java | 2 + .../anc/library/activity/ProfileActivity.java | 2 + .../fragment/ProfileContactsFragment.java | 153 +++++++++++++----- opensrp-anc/src/main/res/values/strings.xml | 2 + reference-app/build.gradle | 5 +- .../anc/activity/LoginActivity.java | 4 + 7 files changed, 127 insertions(+), 43 deletions(-) diff --git a/opensrp-anc/build.gradle b/opensrp-anc/build.gradle index 74142a1..074f024 100644 --- a/opensrp-anc/build.gradle +++ b/opensrp-anc/build.gradle @@ -259,6 +259,7 @@ dependencies { implementation 'org.jacoco:org.jacoco.agent:0.8.7:runtime' testImplementation 'org.jacoco:org.jacoco.agent:0.8.7:runtime' implementation 'org.smartregister:android-p2p-sync:0.4.0-DEV-SNAPSHOT' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda' testImplementation 'junit:junit:4.13.1' testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3' @@ -283,6 +284,7 @@ dependencies { androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0') { exclude group: 'com.google.code.findbugs' } + debugImplementation 'com.amitshekhar.android:debug-db-encrypt:1.0.6' } task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', /*'createDebugCoverageReport'*/]) { diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/BaseHomeRegisterActivity.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/BaseHomeRegisterActivity.java index f0a9462..8bf85e7 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/BaseHomeRegisterActivity.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/BaseHomeRegisterActivity.java @@ -16,6 +16,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; +import com.amitshekhar.DebugDB; import com.google.android.gms.vision.barcode.Barcode; import com.google.android.material.bottomnavigation.LabelVisibilityMode; import com.vijay.jsonwizard.activities.FormConfigurationJsonFormActivity; @@ -28,6 +29,7 @@ import org.json.JSONObject; import org.smartregister.AllConstants; import org.smartregister.anc.library.AncLibrary; +import org.smartregister.anc.library.BuildConfig; import org.smartregister.anc.library.R; import org.smartregister.anc.library.contract.RegisterContract; import org.smartregister.anc.library.domain.AttentionFlag; diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java index a83199b..2385c1f 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java @@ -17,6 +17,7 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.constraintlayout.widget.ConstraintLayout; @@ -49,6 +50,7 @@ import java.io.Serializable; import java.util.HashMap; +import java.util.Objects; import timber.log.Timber; diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java index c95d318..59fb4ae 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java @@ -1,7 +1,7 @@ package org.smartregister.anc.library.fragment; +import android.app.Activity; import android.content.ContentValues; -import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; @@ -13,14 +13,19 @@ import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; -import org.apache.commons.lang3.StringUtils; +import android.widget.Toast; + import androidx.constraintlayout.widget.ConstraintLayout; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import org.apache.commons.lang3.StringUtils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; + import org.jeasy.rules.api.Facts; import org.joda.time.LocalDate; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.smartregister.anc.library.AncLibrary; @@ -35,30 +40,32 @@ import org.smartregister.anc.library.domain.YamlConfig; import org.smartregister.anc.library.domain.YamlConfigItem; import org.smartregister.anc.library.domain.YamlConfigWrapper; -import org.smartregister.anc.library.model.PreviousContact; import org.smartregister.anc.library.model.Task; import org.smartregister.anc.library.presenter.ProfileFragmentPresenter; import org.smartregister.anc.library.repository.PatientRepository; -import org.smartregister.anc.library.repository.RegisterQueryProvider; import org.smartregister.anc.library.rule.ContactRule; +import org.smartregister.anc.library.sync.BaseAncClientProcessorForJava; import org.smartregister.anc.library.util.ANCJsonFormUtils; -import org.smartregister.anc.library.util.AppExecutors; import org.smartregister.anc.library.util.ConstantsUtils; import org.smartregister.anc.library.util.DBConstantsUtils; import org.smartregister.anc.library.util.FilePathUtils; import org.smartregister.anc.library.util.Utils; -import org.smartregister.p2p.exceptions.AsyncTaskCancelledException; +import org.smartregister.domain.Event; import org.smartregister.view.fragment.BaseProfileFragment; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import timber.log.Timber; @@ -122,9 +129,10 @@ protected void onCreation() { } buttonAlertStatus = Utils.getButtonAlertStatus(clientDetails, getActivity(), true); - if(clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")){ + if (clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")) { buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; } + } } @@ -200,26 +208,30 @@ private void populatePreviousContactMissingEssentials(HashMap cl private void setUpAlertStatusButton() { Utils.processButtonAlertStatus(getActivity(), dueButton, buttonAlertStatus); - if(buttonAlertStatus.buttonAlertStatus.equals(ConstantsUtils.AlertStatusUtils.REGENERATE)){ - dueButton.setOnClickListener(view -> new RegenerateContactSchedulesTask(clientDetails).execute()); + if (buttonAlertStatus.buttonAlertStatus.equals(ConstantsUtils.AlertStatusUtils.REGENERATE)) { + dueButton.setOnClickListener(view -> { + Toast.makeText(getActivity(), "Regenerating Contact Schedule", Toast.LENGTH_SHORT).show(); + new RegenerateContactSchedulesTask(clientDetails, getActivity()).execute(); + }); } +// buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; } private void initializeLastContactDetails(HashMap clientDetails) { if (clientDetails != null) { - List lastContactDetailsWrapperList = new ArrayList<>(); - List lastContactDetailsTestsWrapperList = new ArrayList<>(); - Facts facts = presenter.getImmediatePreviousContact(clientDetails, baseEntityId, contactNo); - try { - addOtherRuleObjects(facts); - addAttentionFlagsRuleObjects(facts); - contactNo = (String) facts.asMap().get(ConstantsUtils.CONTACT_NO); - - addTestsRuleObjects(facts); - } catch (IOException e) { - throw new RuntimeException(e); - } + List lastContactDetailsWrapperList = new ArrayList<>(); + List lastContactDetailsTestsWrapperList = new ArrayList<>(); + Facts facts = presenter.getImmediatePreviousContact(clientDetails, baseEntityId, contactNo); + try { + addOtherRuleObjects(facts); + addAttentionFlagsRuleObjects(facts); + contactNo = (String) facts.asMap().get(ConstantsUtils.CONTACT_NO); + + addTestsRuleObjects(facts); + } catch (IOException e) { + throw new RuntimeException(e); + } String displayContactDate = ""; // If no visit date, try to get contact date @@ -366,9 +378,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa dueButton = ((ProfileActivity) getActivity()).getDueButton(); // if (!ConstantsUtils.AlertStatusUtils.TODAY.equals(buttonAlertStatus.buttonAlertStatus)) { - dueButton.setOnClickListener((ProfileActivity) getActivity()); + dueButton.setOnClickListener((ProfileActivity) getActivity()); // } else { - dueButton.setEnabled(true); + dueButton.setEnabled(true); // } return fragmentView; @@ -430,27 +442,36 @@ public void onClick(View view) { public class RegenerateContactSchedulesTask extends AsyncTask { HashMap details; + Activity activity; - RegenerateContactSchedulesTask(HashMap details){ + RegenerateContactSchedulesTask(HashMap details, Activity context) { this.details = details; + this.activity = context; } + @Override protected String doInBackground(Void... voids) { - boolean isFirst = TextUtils.equals("1", details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT)); - int gestationAge = details.containsKey(DBConstantsUtils.KeyUtils.EDD) && details.get(DBConstantsUtils.KeyUtils.EDD) != null ? Utils - .getGestationAgeFromEDDate(details.get(DBConstantsUtils.KeyUtils.EDD)) : 4; - ContactRule contactRule = new ContactRule(gestationAge, isFirst, baseEntityId); - List integerList = AncLibrary.getInstance().getAncRulesEngineHelper() - .getContactVisitSchedule(contactRule, ConstantsUtils.RulesFileUtils.CONTACT_RULES); + try { + int contactNo = 1; + if (details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT) != null) { + contactNo = Integer.parseInt(Objects.requireNonNull(details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT))) - 1; + } + + boolean isFirst = contactNo == 1; + int gestationAge = Utils.getLastContactGA(details.get(DBConstantsUtils.KeyUtils.EDD), details.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE)); + ContactRule contactRule = new ContactRule(gestationAge, isFirst, baseEntityId); - int nextContactVisitWeeks = integerList.get(0); - JSONObject jsonObject = new JSONObject(); - try { - jsonObject.put(ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, integerList); - AncLibrary.getInstance().getDetailsRepository().add(baseEntityId, ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, jsonObject.toString(), + List integerList = AncLibrary.getInstance().getAncRulesEngineHelper() + .getContactVisitSchedule(contactRule, ConstantsUtils.RulesFileUtils.CONTACT_RULES); + + int nextContactVisitWeeks = integerList.get(0); + + JSONObject contactScheduleObject = new JSONObject(); + contactScheduleObject.put(ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, integerList); + AncLibrary.getInstance().getDetailsRepository().add(baseEntityId, ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, contactScheduleObject.toString(), Calendar.getInstance().getTimeInMillis()); ContentValues ecClientsCv = new ContentValues(); @@ -464,20 +485,68 @@ protected String doInBackground(Void... voids) { ecMotherDetailsCv.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT_DATE, nextContactVisitDate); PatientRepository.updatePatient(baseEntityId, ecMotherDetailsCv, DBConstantsUtils.RegisterTable.DETAILS); + JSONObject eventsForBaseEntityId = AncLibrary.getInstance().getEventClientRepository().getEventsByBaseEntityId(baseEntityId); + + + JSONArray jsonArray = eventsForBaseEntityId.getJSONArray("events"); + int bound = eventsForBaseEntityId.getJSONArray("events").length(); + List visits = new ArrayList<>(); + for (int i = 0; i < bound; i++) { + JSONObject eventObject = jsonArray.getJSONObject(i); + if ("Contact Visit".equals(eventObject.optString("eventType"))) { + visits.add(eventObject); + } + } + + String contactKey = "Contact " + details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT); + + for (int j = 0; j < visits.size(); j++) { + JSONObject details = visits.get(j).getJSONObject("details"); + if (details.get("Contact").equals(contactKey)) { + JSONObject visitToUpdate = visits.get(j); + // remove details since it is causing errors during deserialization + visitToUpdate.remove("details"); + ObjectMapper objectMapper = new ObjectMapper(); + // Register JodaModule + objectMapper.registerModule(new JodaModule()); + Event visitEvent = objectMapper.readValue(visitToUpdate.toString(), Event.class); + JSONObject previousContact = new JSONObject(details.get("previous_contacts").toString()); + previousContact.put("contact_schedule", contactScheduleObject.toString()); + details.put("previous_contacts", previousContact.toString()); + + Map eventDetails = new HashMap<>(); + Iterator keys = details.keys(); + while (keys.hasNext()) { + String key = (String) keys.next(); + eventDetails.put(key, (String) details.get(key)); + } + visitEvent.setDetails(eventDetails); + + BaseAncClientProcessorForJava baseAncClientProcessorForJava = BaseAncClientProcessorForJava.getInstance(getActivity()); + Method processVisitMethod = baseAncClientProcessorForJava.getClass().getDeclaredMethod("processVisit", Event.class); + processVisitMethod.setAccessible(true); + + processVisitMethod.invoke(baseAncClientProcessorForJava, visitEvent); + break; + } + } return "success"; - } catch (JSONException e) { + } catch (JSONException | NoSuchMethodException | JsonProcessingException | + InvocationTargetException | IllegalAccessException e) { Timber.e(e); + return "failure"; } - return "failure"; + } @Override - protected void onPostExecute(String message){ - if(message.equals("success")){ - - } + protected void onPostExecute(String message) { + if (message.equals("success")) { + Toast.makeText(activity, R.string.successfully_updated_contact_schedule, Toast.LENGTH_LONG ).show(); + } else Toast.makeText(activity, R.string.an_error_occurred_while_regenerating_contact_schedule, Toast.LENGTH_LONG ).show(); + activity.finish(); } diff --git a/opensrp-anc/src/main/res/values/strings.xml b/opensrp-anc/src/main/res/values/strings.xml index d5256db..527389e 100644 --- a/opensrp-anc/src/main/res/values/strings.xml +++ b/opensrp-anc/src/main/res/values/strings.xml @@ -477,5 +477,7 @@ Expected deliveries Late visits Regenerate Contact Schedule + Successfully updated contact schedule + An error occurred while regenerating contact schedule \ No newline at end of file diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 099cef6..0a55bce 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -26,7 +26,7 @@ jacoco { // This variables are used by the version code & name generators ext.versionMajor = 1 ext.versionMinor = 6 -ext.versionPatch = 27 +ext.versionPatch = 29 ext.versionClassifier = null ext.isSnapshot = false ext.minimumSdkVersion = androidMinSdkVersion @@ -328,6 +328,7 @@ dependencies { } implementation 'com.google.firebase:firebase-perf' implementation 'com.android.volley:volley:1.2.1' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda' testImplementation 'junit:junit:4.13.1' testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3' @@ -347,6 +348,8 @@ dependencies { testImplementation 'org.mockito:mockito-core:3.5.15' testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3' testImplementation 'org.skyscreamer:jsonassert:1.5.0' + + debugImplementation 'com.amitshekhar.android:debug-db-encrypt:1.0.6' } task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) { diff --git a/reference-app/src/main/java/org/smartregister/anc/activity/LoginActivity.java b/reference-app/src/main/java/org/smartregister/anc/activity/LoginActivity.java index 8469036..fe91219 100644 --- a/reference-app/src/main/java/org/smartregister/anc/activity/LoginActivity.java +++ b/reference-app/src/main/java/org/smartregister/anc/activity/LoginActivity.java @@ -5,9 +5,12 @@ import android.view.View; import android.widget.TextView; +import com.amitshekhar.DebugDB; + import org.apache.commons.lang3.StringUtils; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import org.smartregister.anc.BuildConfig; import org.smartregister.anc.library.R; import org.smartregister.anc.library.activity.BaseHomeRegisterActivity; import org.smartregister.anc.library.activity.SiteCharacteristicsEnterActivity; @@ -34,6 +37,7 @@ protected void onResume() { if (!mLoginPresenter.isUserLoggedOut()) { goToHome(false); } + } @Override From f4170abc2b68d0a1bc32ab5ded3adf37337437f6 Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Wed, 19 Jun 2024 10:49:39 +0300 Subject: [PATCH 06/11] mark event as unsynced for resync --- .../anc/library/fragment/ProfileContactsFragment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java index 59fb4ae..cb70a25 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java @@ -527,6 +527,8 @@ protected String doInBackground(Void... voids) { processVisitMethod.setAccessible(true); processVisitMethod.invoke(baseAncClientProcessorForJava, visitEvent); + // mark event as UnSynced and Invalid so that it can be uploaded in the next sync cycle + AncLibrary.getInstance().getEventClientRepository().markEventValidationStatus(visitEvent.getFormSubmissionId(), false); break; } } From 65f64e08c8028c3a5f694422bc16d6845a7587aa Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Wed, 19 Jun 2024 17:22:13 +0300 Subject: [PATCH 07/11] add visit date to woman detail --- opensrp-anc/src/main/assets/ec_client_fields.json | 10 ++++++++-- .../anc/library/interactor/ContactInteractor.java | 2 +- .../anc/library/repository/PatientRepository.java | 12 ++++++++++++ .../library/repository/RegisterQueryProvider.java | 1 + .../org/smartregister/anc/library/util/Utils.java | 12 ++++++------ reference-app/build.gradle | 4 ++-- .../smartregister/anc/repository/AncRepository.java | 10 ++++++++++ 7 files changed, 40 insertions(+), 11 deletions(-) diff --git a/opensrp-anc/src/main/assets/ec_client_fields.json b/opensrp-anc/src/main/assets/ec_client_fields.json index 682eb4b..bb127ce 100644 --- a/opensrp-anc/src/main/assets/ec_client_fields.json +++ b/opensrp-anc/src/main/assets/ec_client_fields.json @@ -209,8 +209,7 @@ "field": "attributes.sector" } - } - , + }, { "column_name": "cell", "type": "Client", @@ -231,6 +230,13 @@ "json_mapping": { "field": "attributes.visit_start_date" } + }, + { + "column_name": "visit_date", + "type": "Client", + "json_mapping": { + "field": "attributes.visit_date" + } } ] }, diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java index 59523ba..1b12567 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java @@ -198,10 +198,10 @@ private void updateWomanDetails(Map details, WomanDetail womanDe details.put(DBConstantsUtils.KeyUtils.CONTACT_STATUS, womanDetail.getContactStatus()); } else { details.put(DBConstantsUtils.KeyUtils.CONTACT_STATUS, womanDetail.getContactStatus()); - details.put(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE, Utils.getDBDateToday()); details.put(DBConstantsUtils.KeyUtils.YELLOW_FLAG_COUNT, womanDetail.getYellowFlagCount().toString()); details.put(DBConstantsUtils.KeyUtils.RED_FLAG_COUNT, womanDetail.getRedFlagCount().toString()); + details.put(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE, Utils.getDBDateToday()); } details.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT, womanDetail.getNextContact().toString()); details.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT_DATE, womanDetail.getNextContactDate()); diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java index 0ced2a4..bbf222c 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java @@ -193,6 +193,18 @@ public static void updateLastContactDate(String baseEntityId, String edd) { // } updatePatient(baseEntityId, contentValues, getRegisterQueryProvider().getDetailsTable()); } + + public static void updateLastVisitDate(String baseEntityId, String visitDate) { + + ContentValues contentValues = new ContentValues(); + if (visitDate != null) { + contentValues.put(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE, visitDate); + } else { + contentValues.putNull(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); + } + updatePatient(baseEntityId, contentValues, getRegisterQueryProvider().getDetailsTable()); + } + public static void updateContactVisitStartDate(String baseEntityId, String contactVisitStartDate) { ContentValues contentValues = new ContentValues(); diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java index f5e8f79..cec9ea3 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/RegisterQueryProvider.java @@ -84,6 +84,7 @@ DBConstantsUtils.KeyUtils.DOB_UNKNOWN, getDetailsTable() + "." + DBConstantsUtil getDetailsTable() + "." + ConstantsUtils.SpinnerKeyConstants.VILLAGE ,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.INSURANCE, getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.VILLAGE,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.UBUDEHE_CATEGORY, getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.NATIONAL_ID,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.DOCUMENT_TYPE, + getDetailsTable() + "." + ConstantsUtils.JsonFormKeyUtils.VISIT_DATE, getDemographicTable()+ "." + ConstantsUtils.DATA_MIGRATION_IS_DIRTY, getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.PASSPORT_ID,getDetailsTable()+ "." + DBConstantsUtils.KeyUtils.OTHER_ID }; diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java index 86139e5..bf81a93 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java @@ -112,7 +112,7 @@ public class Utils extends org.smartregister.util.Utils { public static final String HOME_ADDRESS = "Home Address"; private static final DateTimeFormatter SQLITE_DATE_DF = DateTimeFormat.forPattern(ConstantsUtils.SQLITE_DATE_TIME_FORMAT); private static final String OTHER_SUFFIX = ", other]"; - private static String visitDate; + private static String mVisitDate; static { ALLOWED_LEVELS = new ArrayList<>(); @@ -475,9 +475,9 @@ public static int getGestationAgeFromEDDate(String expectedDeliveryDate) { LocalDate date = SQLITE_DATE_DF.withOffsetParsed().parseLocalDate(expectedDeliveryDate); LocalDate lmpDate = date.minusWeeks(ConstantsUtils.DELIVERY_DATE_WEEKS); Weeks weeks; - if (visitDate != null) { + if (mVisitDate != null) { weeks = Weeks.weeksBetween(lmpDate, DateTimeFormat.forPattern("dd-MM-yyyy").withOffsetParsed() - .parseLocalDate(visitDate)); + .parseLocalDate(mVisitDate)); } else weeks = Weeks.weeksBetween(lmpDate, LocalDate.now()); return weeks.getWeeks(); } else { @@ -1071,7 +1071,7 @@ public String getManifestVersion(Context context) { } public void createSavePdf(Context context, List yamlConfigList, Facts facts, String womanName) throws FileNotFoundException { - setVisitDate(facts); +// setmVisitDate(facts); String FILENAME = womanName + "_" + context.getResources().getString(R.string.contact_summary_data_file); String filePath = getAppPath(context) + FILENAME; @@ -1294,8 +1294,8 @@ public static Calendar nextWeekday(Calendar date) { } } - public static void setVisitDate(Facts facts) { - visitDate = facts.get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); + public static void setmVisithstDate(Facts facts) { + mVisitDate = facts.get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); } public static String calculateGaBasedOnUltrasoundEdd(String ultrasoundDateEddDateString, String manualEncounterDateString) { diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 0a55bce..624d30a 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -153,7 +153,7 @@ android { buildConfigField "int", "OPENMRS_UNIQUE_ID_INITIAL_BATCH_SIZE", '250' buildConfigField "int", "OPENMRS_UNIQUE_ID_BATCH_SIZE", '100' buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '1' - buildConfigField "int", "DATABASE_VERSION", '4' + buildConfigField "int", "DATABASE_VERSION", '5' buildConfigField "long", "MAX_SERVER_TIME_DIFFERENCE", "1800000l" buildConfigField "boolean", "TIME_CHECK", "false" buildConfigField "int", "DATA_SYNC_DURATION_MINUTES", '15' @@ -172,7 +172,7 @@ android { buildConfigField "int", "OPENMRS_UNIQUE_ID_INITIAL_BATCH_SIZE", '250' buildConfigField "int", "OPENMRS_UNIQUE_ID_BATCH_SIZE", '100' buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '1' - buildConfigField "int", "DATABASE_VERSION", '4' + buildConfigField "int", "DATABASE_VERSION", '5' buildConfigField "long", "MAX_SERVER_TIME_DIFFERENCE", "1800000l" buildConfigField "boolean", "TIME_CHECK", "false" buildConfigField "int", "DATA_SYNC_DURATION_MINUTES", '15' diff --git a/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java b/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java index 2fea2fa..5b1599f 100644 --- a/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java +++ b/reference-app/src/main/java/org/smartregister/anc/repository/AncRepository.java @@ -75,6 +75,9 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { case 4: upgradeToVersion4(db); break; + case 5: + upgradeToVersion5(db); + break; default: break; } @@ -157,6 +160,13 @@ private void upgradeToVersion4(SQLiteDatabase db) { Timber.e("upgradeToVersion4 %s", e.getMessage()); } } + private void upgradeToVersion5(SQLiteDatabase db) { + try { + db.execSQL("ALTER TABLE " + DBConstantsUtils.WOMAN_DETAILS_TABLE_NAME + " ADD COLUMN " + ConstantsUtils.JsonFormKeyUtils.VISIT_DATE + " VARCHAR"); + } catch (Exception e) { + Timber.e("upgradeToVersion5 %s", e.getMessage()); + } + } } From 420ab16383f0cf6e0c6adbac21b0b50fffb1bca9 Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Thu, 20 Jun 2024 14:30:38 +0300 Subject: [PATCH 08/11] Revert to patch version 20 Fix regenerate contact schedule button not appearing consistently Use manual encounter date to calculate ga Fix contact date being displayed in Profile contacts --- .../anc/library/activity/ProfileActivity.java | 35 +++- .../fragment/ProfileContactsFragment.java | 138 ++------------- .../fragment/ProfileOverviewFragment.java | 5 +- .../fragment/ProfileTasksFragment.java | 3 + .../library/interactor/ContactInteractor.java | 11 +- .../library/provider/RegisterProvider.java | 9 + .../library/repository/PatientRepository.java | 7 +- .../task/RegenerateContactSchedulesTask.java | 157 ++++++++++++++++++ .../smartregister/anc/library/util/Utils.java | 41 +++-- reference-app/build.gradle | 2 +- 10 files changed, 262 insertions(+), 146 deletions(-) create mode 100644 opensrp-anc/src/main/java/org/smartregister/anc/library/task/RegenerateContactSchedulesTask.java diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java index 2385c1f..29a9ea7 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java @@ -3,11 +3,13 @@ import android.Manifest; import android.app.Activity; import android.app.AlertDialog; +import android.content.ContentValues; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.net.Uri; +import android.os.AsyncTask; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -24,10 +26,18 @@ import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; + import org.apache.commons.lang3.StringUtils; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import org.joda.time.LocalDate; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import org.smartregister.anc.library.AncLibrary; import org.smartregister.anc.library.R; import org.smartregister.anc.library.adapter.ProfileViewPagerAdapter; @@ -38,18 +48,30 @@ import org.smartregister.anc.library.fragment.ProfileOverviewFragment; import org.smartregister.anc.library.fragment.ProfileTasksFragment; import org.smartregister.anc.library.presenter.ProfilePresenter; +import org.smartregister.anc.library.repository.PatientRepository; +import org.smartregister.anc.library.rule.ContactRule; +import org.smartregister.anc.library.sync.BaseAncClientProcessorForJava; +import org.smartregister.anc.library.task.RegenerateContactSchedulesTask; import org.smartregister.anc.library.util.ANCJsonFormUtils; import org.smartregister.anc.library.util.ConstantsUtils; import org.smartregister.anc.library.util.DBConstantsUtils; import org.smartregister.anc.library.util.Utils; import org.smartregister.anc.library.view.CopyToClipboardDialog; +import org.smartregister.domain.Event; import org.smartregister.repository.AllSharedPreferences; import org.smartregister.util.PermissionUtils; import org.smartregister.util.StringUtil; import org.smartregister.view.activity.BaseProfileActivity; import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Calendar; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Objects; import timber.log.Timber; @@ -156,11 +178,17 @@ public void onClick(View view) { if (view.getId() == R.id.profile_overview_due_button) { String baseEntityId = getIntent().getStringExtra(ConstantsUtils.IntentKeyUtils.BASE_ENTITY_ID); - if (StringUtils.isNotBlank(baseEntityId)) { - Utils.proceedToContact(baseEntityId, detailMap, getActivity()); - finish(); + if ((view.getTag(R.string.regenerate_contact_schedule)).equals(ConstantsUtils.AlertStatusUtils.REGENERATE)) { + new RegenerateContactSchedulesTask(getActivity(), baseEntityId).execute(); + } else { + if (StringUtils.isNotBlank(baseEntityId)) { + Utils.proceedToContact(baseEntityId, detailMap, getActivity()); + finish(); + } } + + } else { super.onClick(view); } @@ -398,4 +426,5 @@ public Button getDueButton() { public ProfilePresenter getProfilePresenter() { return (ProfilePresenter) presenter; } + } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java index cb70a25..4226368 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileContactsFragment.java @@ -129,9 +129,6 @@ protected void onCreation() { } buttonAlertStatus = Utils.getButtonAlertStatus(clientDetails, getActivity(), true); - if (clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")) { - buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; - } } } @@ -207,14 +204,11 @@ private void populatePreviousContactMissingEssentials(HashMap cl } private void setUpAlertStatusButton() { +// if (clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")) { +// buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; +// } Utils.processButtonAlertStatus(getActivity(), dueButton, buttonAlertStatus); - if (buttonAlertStatus.buttonAlertStatus.equals(ConstantsUtils.AlertStatusUtils.REGENERATE)) { - dueButton.setOnClickListener(view -> { - Toast.makeText(getActivity(), "Regenerating Contact Schedule", Toast.LENGTH_SHORT).show(); - new RegenerateContactSchedulesTask(clientDetails, getActivity()).execute(); - }); - } -// buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; + } private void initializeLastContactDetails(HashMap clientDetails) { @@ -235,7 +229,17 @@ private void initializeLastContactDetails(HashMap clientDetails) String displayContactDate = ""; // If no visit date, try to get contact date - String contactDate = (String) facts.asMap().get(ConstantsUtils.CONTACT_DATE); + String contactDate = (String) facts.asMap().get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); + if (contactDate != null) { + contactDate = Utils.reverseHyphenSeperatedValues(contactDate, "-"); + } else { + contactDate = + clientDetails.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE) != null ? + clientDetails.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE) : + (String) facts.asMap().get(ConstantsUtils.CONTACT_DATE); + } + + if (!TextUtils.isEmpty(contactDate)) { // If contact date exists, parse and format for display try { @@ -440,117 +444,5 @@ public void onClick(View view) { } - public class RegenerateContactSchedulesTask extends AsyncTask { - HashMap details; - Activity activity; - - RegenerateContactSchedulesTask(HashMap details, Activity context) { - this.details = details; - this.activity = context; - } - - @Override - protected String doInBackground(Void... voids) { - - - try { - int contactNo = 1; - if (details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT) != null) { - contactNo = Integer.parseInt(Objects.requireNonNull(details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT))) - 1; - } - - boolean isFirst = contactNo == 1; - int gestationAge = Utils.getLastContactGA(details.get(DBConstantsUtils.KeyUtils.EDD), details.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE)); - ContactRule contactRule = new ContactRule(gestationAge, isFirst, baseEntityId); - - - List integerList = AncLibrary.getInstance().getAncRulesEngineHelper() - .getContactVisitSchedule(contactRule, ConstantsUtils.RulesFileUtils.CONTACT_RULES); - - int nextContactVisitWeeks = integerList.get(0); - JSONObject contactScheduleObject = new JSONObject(); - contactScheduleObject.put(ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, integerList); - AncLibrary.getInstance().getDetailsRepository().add(baseEntityId, ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, contactScheduleObject.toString(), - Calendar.getInstance().getTimeInMillis()); - - ContentValues ecClientsCv = new ContentValues(); - ContentValues ecMotherDetailsCv = new ContentValues(); - ecClientsCv.put(ConstantsUtils.DATA_MIGRATION_IS_DIRTY, "0"); - PatientRepository.updatePatient(baseEntityId, ecClientsCv, DBConstantsUtils.RegisterTable.DEMOGRAPHIC); - - LocalDate localDate = new LocalDate(details.get(DBConstantsUtils.KeyUtils.EDD)); - String nextContactVisitDate = - localDate.minusWeeks(ConstantsUtils.DELIVERY_DATE_WEEKS).plusWeeks(nextContactVisitWeeks).toString(); - ecMotherDetailsCv.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT_DATE, nextContactVisitDate); - - PatientRepository.updatePatient(baseEntityId, ecMotherDetailsCv, DBConstantsUtils.RegisterTable.DETAILS); - JSONObject eventsForBaseEntityId = AncLibrary.getInstance().getEventClientRepository().getEventsByBaseEntityId(baseEntityId); - - - JSONArray jsonArray = eventsForBaseEntityId.getJSONArray("events"); - int bound = eventsForBaseEntityId.getJSONArray("events").length(); - List visits = new ArrayList<>(); - for (int i = 0; i < bound; i++) { - JSONObject eventObject = jsonArray.getJSONObject(i); - if ("Contact Visit".equals(eventObject.optString("eventType"))) { - visits.add(eventObject); - } - } - - String contactKey = "Contact " + details.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT); - - for (int j = 0; j < visits.size(); j++) { - JSONObject details = visits.get(j).getJSONObject("details"); - if (details.get("Contact").equals(contactKey)) { - JSONObject visitToUpdate = visits.get(j); - // remove details since it is causing errors during deserialization - visitToUpdate.remove("details"); - ObjectMapper objectMapper = new ObjectMapper(); - // Register JodaModule - objectMapper.registerModule(new JodaModule()); - Event visitEvent = objectMapper.readValue(visitToUpdate.toString(), Event.class); - JSONObject previousContact = new JSONObject(details.get("previous_contacts").toString()); - previousContact.put("contact_schedule", contactScheduleObject.toString()); - details.put("previous_contacts", previousContact.toString()); - - Map eventDetails = new HashMap<>(); - Iterator keys = details.keys(); - while (keys.hasNext()) { - String key = (String) keys.next(); - eventDetails.put(key, (String) details.get(key)); - } - visitEvent.setDetails(eventDetails); - - BaseAncClientProcessorForJava baseAncClientProcessorForJava = BaseAncClientProcessorForJava.getInstance(getActivity()); - Method processVisitMethod = baseAncClientProcessorForJava.getClass().getDeclaredMethod("processVisit", Event.class); - processVisitMethod.setAccessible(true); - - processVisitMethod.invoke(baseAncClientProcessorForJava, visitEvent); - // mark event as UnSynced and Invalid so that it can be uploaded in the next sync cycle - AncLibrary.getInstance().getEventClientRepository().markEventValidationStatus(visitEvent.getFormSubmissionId(), false); - break; - } - } - - return "success"; - } catch (JSONException | NoSuchMethodException | JsonProcessingException | - InvocationTargetException | IllegalAccessException e) { - Timber.e(e); - return "failure"; - } - - - } - - @Override - protected void onPostExecute(String message) { - if (message.equals("success")) { - Toast.makeText(activity, R.string.successfully_updated_contact_schedule, Toast.LENGTH_LONG ).show(); - } else Toast.makeText(activity, R.string.an_error_occurred_while_regenerating_contact_schedule, Toast.LENGTH_LONG ).show(); - activity.finish(); - } - - - } } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java index f07bc69..442f96c 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileOverviewFragment.java @@ -150,9 +150,10 @@ protected void onResumption() { yamlConfigListGlobal.addAll(yamlConfigList); } } - +// if (clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")) { +// buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; +// } Utils.processButtonAlertStatus(getActivity(), dueButton, buttonAlertStatus); - attachRecyclerView(facts); if (yamlConfigListGlobal.isEmpty()) { diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileTasksFragment.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileTasksFragment.java index c83512c..5d2c3af 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileTasksFragment.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/fragment/ProfileTasksFragment.java @@ -93,6 +93,9 @@ protected void onCreation() { @Override protected void onResumption() { +// if (clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY) != null && clientDetails.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")) { +// buttonAlertStatus.buttonAlertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; +// } Utils.processButtonAlertStatus(getActivity(), dueButton, buttonAlertStatus); if (getActivity() != null && getActivity().getIntent() != null) { baseEntityId = getActivity().getIntent().getStringExtra(ConstantsUtils.IntentKeyUtils.BASE_ENTITY_ID); diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java index 1b12567..5be84c6 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/interactor/ContactInteractor.java @@ -200,8 +200,7 @@ private void updateWomanDetails(Map details, WomanDetail womanDe details.put(DBConstantsUtils.KeyUtils.CONTACT_STATUS, womanDetail.getContactStatus()); details.put(DBConstantsUtils.KeyUtils.YELLOW_FLAG_COUNT, womanDetail.getYellowFlagCount().toString()); details.put(DBConstantsUtils.KeyUtils.RED_FLAG_COUNT, womanDetail.getRedFlagCount().toString()); - - details.put(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE, Utils.getDBDateToday()); + details.put(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE, details.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE)); } details.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT, womanDetail.getNextContact().toString()); details.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT_DATE, womanDetail.getNextContactDate()); @@ -262,8 +261,12 @@ protected PreviousContactRepository getPreviousContactRepository() { } public int getGestationAge(Map details) { - return details.containsKey(DBConstantsUtils.KeyUtils.EDD) && details.get(DBConstantsUtils.KeyUtils.EDD) != null ? Utils - .getGestationAgeFromEDDate(details.get(DBConstantsUtils.KeyUtils.EDD)) : 4; + if (!details.containsKey(DBConstantsUtils.KeyUtils.EDD) || details.get(DBConstantsUtils.KeyUtils.EDD) == null) return 4; + String edd = details.get(DBConstantsUtils.KeyUtils.EDD); + String visitDate = details.get(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE); + + if (visitDate == null) return Utils.getGestationAgeFromEDDate(edd); + return Utils.getGAFromEDDateOnVisitDate(edd, visitDate); } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/provider/RegisterProvider.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/provider/RegisterProvider.java index 5714127..6473d85 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/provider/RegisterProvider.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/provider/RegisterProvider.java @@ -1,5 +1,6 @@ package org.smartregister.anc.library.provider; +import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.text.TextUtils; @@ -18,6 +19,8 @@ import org.smartregister.anc.library.R; import org.smartregister.anc.library.domain.ButtonAlertStatus; import org.smartregister.anc.library.fragment.HomeRegisterFragment; +import org.smartregister.anc.library.task.RegenerateContactSchedulesTask; +import org.smartregister.anc.library.util.ConstantsUtils; import org.smartregister.anc.library.util.DBConstantsUtils; import org.smartregister.anc.library.util.Utils; import org.smartregister.commonregistry.CommonPersonObject; @@ -207,6 +210,12 @@ private void populateLastColumn(CommonPersonObjectClient pc, RegisterViewHolder Utils.getButtonAlertStatus(pc.getColumnmaps(), context, false); Utils.processButtonAlertStatus(context, viewHolder.dueButton, viewHolder.contactDoneTodayButton, buttonAlertStatus); + if (buttonAlertStatus.buttonAlertStatus.equals(ConstantsUtils.AlertStatusUtils.REGENERATE)) { + + viewHolder.dueButton.setOnClickListener(view -> { + new RegenerateContactSchedulesTask((Activity) view.getContext(), pc.entityId()); + }); + } } else { viewHolder.dueButton.setVisibility(View.GONE); diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java index bbf222c..40dd61e 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/repository/PatientRepository.java @@ -181,11 +181,12 @@ public static void updateEDDDate(String baseEntityId, String edd) { } updatePatient(baseEntityId, contentValues, getRegisterQueryProvider().getDetailsTable()); } - public static void updateLastContactDate(String baseEntityId, String edd) { + public static void updateLastContactDate(String baseEntityId, String lstVisitDate) { ContentValues contentValues = new ContentValues(); - if (edd != null) { - contentValues.put(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE, edd); + if (lstVisitDate != null) { + contentValues.put(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE, lstVisitDate); + contentValues.put(ConstantsUtils.JsonFormKeyUtils.VISIT_DATE, lstVisitDate); // contentValues.put(DBConstantsUtils.KeyUtils.CONTACT_STATUS, patientDetail.getPreviousContactStatus()) } // else { diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/task/RegenerateContactSchedulesTask.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/task/RegenerateContactSchedulesTask.java new file mode 100644 index 0000000..bb9bd10 --- /dev/null +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/task/RegenerateContactSchedulesTask.java @@ -0,0 +1,157 @@ +package org.smartregister.anc.library.task; + +import android.app.Activity; +import android.content.ContentValues; +import android.os.AsyncTask; +import android.provider.ContactsContract; +import android.widget.Toast; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; + +import org.joda.time.LocalDate; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.smartregister.anc.library.AncLibrary; +import org.smartregister.anc.library.R; +import org.smartregister.anc.library.activity.ProfileActivity; +import org.smartregister.anc.library.repository.PatientRepository; +import org.smartregister.anc.library.rule.ContactRule; +import org.smartregister.anc.library.sync.BaseAncClientProcessorForJava; +import org.smartregister.anc.library.util.ConstantsUtils; +import org.smartregister.anc.library.util.DBConstantsUtils; +import org.smartregister.anc.library.util.Utils; +import org.smartregister.domain.Event; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import timber.log.Timber; + +public class RegenerateContactSchedulesTask extends AsyncTask { + + Activity activity; + + String baseEntityId = ""; + + public RegenerateContactSchedulesTask(Activity context, String baseEntityId) { + this.activity = context; + this.baseEntityId = baseEntityId; + } + + @Override + protected String doInBackground(Void... voids) { + HashMap clientDetails = (HashMap) PatientRepository.getWomanProfileDetails(baseEntityId); + + try { + int contactNo = 1; + if (clientDetails.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT) != null) { + contactNo = Integer.parseInt(Objects.requireNonNull(clientDetails.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT))) - 1; + } + + boolean isFirst = contactNo == 1; + int gestationAge = Utils.getLastContactGA(clientDetails.get(DBConstantsUtils.KeyUtils.EDD), clientDetails.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE)); + ContactRule contactRule = new ContactRule(gestationAge, isFirst, baseEntityId); + + + List integerList = AncLibrary.getInstance().getAncRulesEngineHelper() + .getContactVisitSchedule(contactRule, ConstantsUtils.RulesFileUtils.CONTACT_RULES); + + int nextContactVisitWeeks = integerList.get(0); + + JSONObject contactScheduleObject = new JSONObject(); + contactScheduleObject.put(ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, integerList); + AncLibrary.getInstance().getDetailsRepository().add(baseEntityId, ConstantsUtils.DetailsKeyUtils.CONTACT_SCHEDULE, contactScheduleObject.toString(), + Calendar.getInstance().getTimeInMillis()); + + ContentValues ecClientsCv = new ContentValues(); + ContentValues ecMotherDetailsCv = new ContentValues(); + ecClientsCv.put(ConstantsUtils.DATA_MIGRATION_IS_DIRTY, "0"); + PatientRepository.updatePatient(baseEntityId, ecClientsCv, DBConstantsUtils.RegisterTable.DEMOGRAPHIC); + + LocalDate localDate = new LocalDate(clientDetails.get(DBConstantsUtils.KeyUtils.EDD)); + String nextContactVisitDate = + localDate.minusWeeks(ConstantsUtils.DELIVERY_DATE_WEEKS).plusWeeks(nextContactVisitWeeks).toString(); + ecMotherDetailsCv.put(DBConstantsUtils.KeyUtils.NEXT_CONTACT_DATE, nextContactVisitDate); + + PatientRepository.updatePatient(baseEntityId, ecMotherDetailsCv, DBConstantsUtils.RegisterTable.DETAILS); + JSONObject eventsForBaseEntityId = AncLibrary.getInstance().getEventClientRepository().getEventsByBaseEntityId(baseEntityId); + + + JSONArray jsonArray = eventsForBaseEntityId.getJSONArray("events"); + int bound = eventsForBaseEntityId.getJSONArray("events").length(); + List visits = new ArrayList<>(); + for (int i = 0; i < bound; i++) { + JSONObject eventObject = jsonArray.getJSONObject(i); + if ("Contact Visit".equals(eventObject.optString("eventType"))) { + visits.add(eventObject); + } + } + + String contactKey = "Contact " + clientDetails.get(DBConstantsUtils.KeyUtils.NEXT_CONTACT); + + for (int j = 0; j < visits.size(); j++) { + JSONObject details = visits.get(j).getJSONObject("details"); + if (details.get("Contact").equals(contactKey)) { + JSONObject visitToUpdate = visits.get(j); + // remove details since it is causing errors during deserialization + visitToUpdate.remove("details"); + ObjectMapper objectMapper = new ObjectMapper(); + // Register JodaModule + objectMapper.registerModule(new JodaModule()); + Event visitEvent = objectMapper.readValue(visitToUpdate.toString(), Event.class); + JSONObject previousContact = new JSONObject(details.get("previous_contacts").toString()); + previousContact.put("contact_schedule", contactScheduleObject.toString()); + details.put("previous_contacts", previousContact.toString()); + + Map eventDetails = new HashMap<>(); + Iterator keys = details.keys(); + while (keys.hasNext()) { + String key = (String) keys.next(); + eventDetails.put(key, (String) details.get(key)); + } + visitEvent.setDetails(eventDetails); + + BaseAncClientProcessorForJava baseAncClientProcessorForJava = BaseAncClientProcessorForJava.getInstance(activity); + Method processVisitMethod = baseAncClientProcessorForJava.getClass().getDeclaredMethod("processVisit", Event.class); + processVisitMethod.setAccessible(true); + + processVisitMethod.invoke(baseAncClientProcessorForJava, visitEvent); + // mark event as UnSynced and Invalid so that it can be uploaded in the next sync cycle + AncLibrary.getInstance().getEventClientRepository().markEventValidationStatus(visitEvent.getFormSubmissionId(), false); + break; + } + } + + return "success"; + } catch (JSONException | NoSuchMethodException | JsonProcessingException | + InvocationTargetException | IllegalAccessException e) { + Timber.e(e); + return "failure"; + } + + + } + + @Override + protected void onPostExecute(String message) { + if (message.equals("success")) { + Toast.makeText(activity, R.string.successfully_updated_contact_schedule, Toast.LENGTH_LONG).show(); + } else + Toast.makeText(activity, R.string.an_error_occurred_while_regenerating_contact_schedule, Toast.LENGTH_LONG).show(); + if(activity instanceof ProfileActivity){ + activity.finish(); + } else activity.recreate(); + } + + +} \ No newline at end of file diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java index bf81a93..06349a4 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java @@ -24,7 +24,6 @@ import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; -import com.itextpdf.layout.element.IBlockElement; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.property.HorizontalAlignment; import com.itextpdf.layout.property.TextAlignment; @@ -79,10 +78,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -455,11 +452,16 @@ public static String getDBDateToday() { nextContactDate = StringUtils.isNotBlank(nextContactDate) ? Utils.reverseHyphenSeperatedValues(nextContactDate, "/") : null; - buttonAlertStatus.buttonText = String.format(getDisplayTemplate(context, alertStatus, isProfile), nextContact, (nextContactDate != null ? nextContactDate : - Utils.convertDateFormat(Calendar.getInstance().getTime(), Utils.CONTACT_DF))); + if(details.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY)!= null && details.get(ConstantsUtils.DATA_MIGRATION_IS_DIRTY).equals("1")){ + alertStatus = ConstantsUtils.AlertStatusUtils.REGENERATE; + buttonAlertStatus.buttonText = context.getResources().getString(R.string.regenerate_contact_schedule); + } else { + alertStatus = + Utils.processContactDoneToday(details.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE), alertStatus); + buttonAlertStatus.buttonText = String.format(getDisplayTemplate(context, alertStatus, isProfile), nextContact, (nextContactDate != null ? nextContactDate : + Utils.convertDateFormat(Calendar.getInstance().getTime(), Utils.CONTACT_DF))); + } - alertStatus = - Utils.processContactDoneToday(details.get(DBConstantsUtils.KeyUtils.LAST_CONTACT_RECORD_DATE), alertStatus); buttonAlertStatus.buttonAlertStatus = alertStatus; buttonAlertStatus.gestationAge = gestationAge; @@ -489,6 +491,23 @@ public static int getGestationAgeFromEDDate(String expectedDeliveryDate) { } } + public static int getGAFromEDDateOnVisitDate(String expectedDeliveryDate, String visitDate) { + try { + if (visitDate != null && !"0".equals(expectedDeliveryDate) && expectedDeliveryDate.length() > 0) { + LocalDate date = SQLITE_DATE_DF.withOffsetParsed().parseLocalDate(expectedDeliveryDate); + LocalDate visitDateLocal = SQLITE_DATE_DF.withOffsetParsed().parseLocalDate(visitDate); + LocalDate lmpDate = date.minusWeeks(ConstantsUtils.DELIVERY_DATE_WEEKS); + Weeks weeks = Weeks.weeksBetween(lmpDate, visitDateLocal); + return weeks.getWeeks(); + } else { + return 0; + } + } catch (Exception e) { + Timber.e(e, " --> getGestationAgeFromEDDate"); + return 0; + } + } + public static String reverseHyphenSeperatedValues(String rawString, String outputSeparator) { if (StringUtils.isNotBlank(rawString)) { String resultString = rawString; @@ -602,7 +621,9 @@ public static void processButtonAlertStatus(Context context, Button dueButton, T Utils.getTodayContact(String.valueOf(buttonAlertStatus.nextContact)))); break; case ConstantsUtils.AlertStatusUtils.REGENERATE: - dueButton.setText(R.string.regenerate_contact_schedule); + dueButton.setText(R.string.regenerate_contact_schedule); + dueButton.setTag(R.string.regenerate_contact_schedule, ConstantsUtils.AlertStatusUtils.REGENERATE); + break; default: dueButton.setBackground(context.getResources().getDrawable(R.drawable.contact_due)); dueButton.setTextColor(context.getResources().getColor(R.color.vaccine_blue_bg_st)); @@ -1301,8 +1322,8 @@ public static void setmVisithstDate(Facts facts) { public static String calculateGaBasedOnUltrasoundEdd(String ultrasoundDateEddDateString, String manualEncounterDateString) { if (ultrasoundDateEddDateString != null && manualEncounterDateString != null) { DateTimeFormatter formatter = DateTimeFormat.forPattern(ConstantsUtils.OPENSRP_DATE_TIME_FORMAT); - LocalDate ultrasoundDateEddDate = LocalDate.parse(ultrasoundDateEddDateString, formatter); - LocalDate manualEncounterDate = LocalDate.parse(manualEncounterDateString, formatter); + LocalDate ultrasoundDateEddDate = LocalDate.parse(ultrasoundDateEddDateString, formatter); + LocalDate manualEncounterDate = LocalDate.parse(manualEncounterDateString, formatter); Days interval = Days.daysBetween(manualEncounterDate, ultrasoundDateEddDate); long daysBetween = 280 - Math.abs(interval.getDays()); diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 624d30a..8f44271 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -26,7 +26,7 @@ jacoco { // This variables are used by the version code & name generators ext.versionMajor = 1 ext.versionMinor = 6 -ext.versionPatch = 29 +ext.versionPatch = 21 ext.versionClassifier = null ext.isSnapshot = false ext.minimumSdkVersion = androidMinSdkVersion From 3921a54d41dc08dcbf45ebb6a563ca2531dfd5fd Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Thu, 20 Jun 2024 17:36:34 +0300 Subject: [PATCH 09/11] Fix null pointer exception --- opensrp-anc/src/main/assets/json.form/anc_quick_check.json | 2 +- .../smartregister/anc/library/activity/ProfileActivity.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opensrp-anc/src/main/assets/json.form/anc_quick_check.json b/opensrp-anc/src/main/assets/json.form/anc_quick_check.json index ccc98ec..93f680d 100644 --- a/opensrp-anc/src/main/assets/json.form/anc_quick_check.json +++ b/opensrp-anc/src/main/assets/json.form/anc_quick_check.json @@ -104,7 +104,7 @@ "type": "date_picker", "hint": "Date of Contact", "expanded": "false", - "min_date": "today-1m", + "min_date": "today-6m", "max_date": "today", "v_required": { "value": true, diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java index 29a9ea7..fc5af25 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/activity/ProfileActivity.java @@ -177,8 +177,8 @@ protected ViewPager setupViewPager(ViewPager viewPager) { public void onClick(View view) { if (view.getId() == R.id.profile_overview_due_button) { String baseEntityId = getIntent().getStringExtra(ConstantsUtils.IntentKeyUtils.BASE_ENTITY_ID); - - if ((view.getTag(R.string.regenerate_contact_schedule)).equals(ConstantsUtils.AlertStatusUtils.REGENERATE)) { + Object viewTag = view.getTag(R.string.regenerate_contact_schedule); + if (viewTag!= null && (viewTag).equals(ConstantsUtils.AlertStatusUtils.REGENERATE)) { new RegenerateContactSchedulesTask(getActivity(), baseEntityId).execute(); } else { if (StringUtils.isNotBlank(baseEntityId)) { From 961bb26cd8b8fad7f4d5efdfa831f074981c406f Mon Sep 17 00:00:00 2001 From: hilary egesa Date: Thu, 1 Aug 2024 09:50:04 +0300 Subject: [PATCH 10/11] increase heap and add leakcanary --- reference-app/build.gradle | 2 +- reference-app/src/main/AndroidManifest.xml | 1 + .../java/org/smartregister/anc/activity/LoginActivity.java | 4 ---- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 8f44271..4a67043 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -349,7 +349,7 @@ dependencies { testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3' testImplementation 'org.skyscreamer:jsonassert:1.5.0' - debugImplementation 'com.amitshekhar.android:debug-db-encrypt:1.0.6' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14' } task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) { diff --git a/reference-app/src/main/AndroidManifest.xml b/reference-app/src/main/AndroidManifest.xml index 500db02..9f4e559 100644 --- a/reference-app/src/main/AndroidManifest.xml +++ b/reference-app/src/main/AndroidManifest.xml @@ -19,6 +19,7 @@ Date: Tue, 13 Aug 2024 12:56:42 +0300 Subject: [PATCH 11/11] use workmanager for syncsetttings --- opensrp-anc/build.gradle | 2 +- opensrp-anc/src/main/AndroidManifest.xml | 4 +++- reference-app/build.gradle | 1 - .../org/smartregister/anc/interactor/LoginInteractor.java | 8 +++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/opensrp-anc/build.gradle b/opensrp-anc/build.gradle index 074f024..ce04d81 100644 --- a/opensrp-anc/build.gradle +++ b/opensrp-anc/build.gradle @@ -191,7 +191,7 @@ dependencies { exclude group: 'org.yaml', module: 'snakeyaml' exclude group: 'io.ona.rdt-capture', module: 'lib' } - implementation('org.smartregister:opensrp-client-core:6.1.2-SNAPSHOT@aar') { + implementation('org.smartregister:opensrp-client-core:6.1.5-ALPHA8-SNAPSHOT@aar') { transitive = true exclude group: 'com.github.bmelnychuk', module: 'atv' exclude group: 'com.google.guava', module: 'guava' diff --git a/opensrp-anc/src/main/AndroidManifest.xml b/opensrp-anc/src/main/AndroidManifest.xml index 42c1376..815925e 100644 --- a/opensrp-anc/src/main/AndroidManifest.xml +++ b/opensrp-anc/src/main/AndroidManifest.xml @@ -38,7 +38,9 @@ android:name="org.smartregister.sync.intent.P2pProcessRecordsService" android:description="@string/component_desc_p2p_process_records_service" android:exported="false" /> - + \ No newline at end of file diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 4a67043..34e0af9 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -311,7 +311,6 @@ dependencies { implementation 'org.jeasy:easy-rules-core:3.3.0' implementation 'org.jeasy:easy-rules-mvel:3.3.0' implementation 'com.flurry.android:analytics:11.6.0@aar' - implementation 'com.flurry.android:analytics:11.6.0@aar' implementation 'androidx.multidex:multidex:2.0.1' // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:28.3.1') diff --git a/reference-app/src/main/java/org/smartregister/anc/interactor/LoginInteractor.java b/reference-app/src/main/java/org/smartregister/anc/interactor/LoginInteractor.java index 151fe6d..af5e604 100644 --- a/reference-app/src/main/java/org/smartregister/anc/interactor/LoginInteractor.java +++ b/reference-app/src/main/java/org/smartregister/anc/interactor/LoginInteractor.java @@ -10,7 +10,9 @@ import org.smartregister.job.SyncAllLocationsServiceJob; import org.smartregister.job.SyncServiceJob; import org.smartregister.job.SyncSettingsServiceJob; +import org.smartregister.job.SyncSettingsServiceWorker; import org.smartregister.login.interactor.BaseLoginInteractor; +import org.smartregister.sync.intent.SettingsSyncIntentService; import org.smartregister.view.contract.BaseLoginContract; import java.util.concurrent.TimeUnit; @@ -37,12 +39,12 @@ protected void scheduleJobsPeriodically() { ImageUploadServiceJob .scheduleJob(ImageUploadServiceJob.TAG, TimeUnit.MINUTES.toMillis(BuildConfig.IMAGE_UPLOAD_MINUTES), getFlexValue(BuildConfig.IMAGE_UPLOAD_MINUTES)); - SyncSettingsServiceJob - .scheduleJob(SyncSettingsServiceJob.TAG, TimeUnit.MINUTES.toMillis(BuildConfig.CLIENT_SETTINGS_SYNC_MINUTES), - getFlexValue(BuildConfig.CLIENT_SETTINGS_SYNC_MINUTES)); + DocumentConfigurationServiceJob .scheduleJob(DocumentConfigurationServiceJob.TAG, TimeUnit.MINUTES.toMillis(BuildConfig.CLIENT_SETTINGS_SYNC_MINUTES), getFlexValue(BuildConfig.CLIENT_SETTINGS_SYNC_MINUTES)); + + SyncSettingsServiceWorker.enqueuePeriodicSettingsSyncIntentService(getApplicationContext()); } @Override