diff --git a/opensrp-chw/build.gradle b/opensrp-chw/build.gradle index afc046ecc2..7dbd3b1c6b 100644 --- a/opensrp-chw/build.gradle +++ b/opensrp-chw/build.gradle @@ -351,8 +351,8 @@ android { lmh { dimension = 'baseDimension' applicationIdSuffix ".lmh" - versionCode 2 - versionName "2.0.1-rc5" + versionCode 4 + versionName "2.0.1" buildConfigField "int", "OPENMRS_UNIQUE_ID_INITIAL_BATCH_SIZE", '10000' buildConfigField "int", "OPENMRS_UNIQUE_ID_BATCH_SIZE", '10000' buildConfigField "int", "OPENMRS_UNIQUE_ID_SOURCE", '1' @@ -378,7 +378,7 @@ dependencies { implementation('com.google.android.gms:play-services-vision:17.0.2') - implementation('org.smartregister:opensrp-client-chw-core:2.1.4-LMH-Beta-04-SNAPSHOT@aar') { + implementation('org.smartregister:opensrp-client-chw-core:2.1.4-SNAPSHOT@aar') { transitive = true exclude group: 'com.android.support', module: 'appcompat-v7' exclude group: 'androidx.legacy', module: 'legacy-support-v4' diff --git a/opensrp-chw/src/lmh/java/org/smartregister/chw/application/ChwApplicationFlv.java b/opensrp-chw/src/lmh/java/org/smartregister/chw/application/ChwApplicationFlv.java index 052bb0020f..6994a9c967 100644 --- a/opensrp-chw/src/lmh/java/org/smartregister/chw/application/ChwApplicationFlv.java +++ b/opensrp-chw/src/lmh/java/org/smartregister/chw/application/ChwApplicationFlv.java @@ -1,5 +1,8 @@ package org.smartregister.chw.application; +import org.smartregister.chw.anc.domain.MemberObject; +import org.smartregister.chw.dao.ChwChildDao; + public class ChwApplicationFlv extends DefaultChwApplicationFlv { @Override @@ -229,22 +232,42 @@ public boolean greyOutFormActionsIfInvalid() { @Override public boolean checkExtraForDueInFamily() { - return true; + return true; } + @Override - public boolean hideCaregiverAndFamilyHeadWhenOnlyOneAdult(){ + public boolean hideCaregiverAndFamilyHeadWhenOnlyOneAdult() { return true; } @Override - public boolean showsPhysicallyDisabledView() { return false; } + public boolean showsPhysicallyDisabledView() { + return false; + } @Override - public boolean vaccinesDefaultChecked() { return false; } + public boolean vaccinesDefaultChecked() { + return false; + } @Override public boolean checkDueStatusFromUpcomingServices() { return true; } + + @Override + public int immunizationCeilingMonths(MemberObject memberObject) { + String gender = ChwChildDao.getChildGender(memberObject.getBaseEntityId()); + + if (gender != null && gender.equalsIgnoreCase("Female")) { + if (memberObject.getAge() >= 9 && memberObject.getAge() <= 11) { + return 132; + } else { + return 60; + } + } + + return 60; + } } diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/activity/ChildProfileActivity.java b/opensrp-chw/src/main/java/org/smartregister/chw/activity/ChildProfileActivity.java index b3d3851b45..0edbc290ce 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/activity/ChildProfileActivity.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/activity/ChildProfileActivity.java @@ -141,6 +141,12 @@ protected void initializePresenter() { @Override protected void setupViews() { super.setupViews(); + if (ChwApplication.getApplicationFlavor().checkDueStatusFromUpcomingServices()) { + // Initially hide visit bar, that would be made visible after due services are checked + findViewById(R.id.record_visit_bar) + .setVisibility(View.GONE); + } + familyFloatingMenu = new FamilyMemberFloatingMenu(this); LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams( diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/application/ChwApplication.java b/opensrp-chw/src/main/java/org/smartregister/chw/application/ChwApplication.java index 7a74c83292..ed8d838239 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/application/ChwApplication.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/application/ChwApplication.java @@ -44,6 +44,7 @@ import org.smartregister.chw.activity.ReportsActivity; import org.smartregister.chw.activity.UpdatesRegisterActivity; import org.smartregister.chw.anc.AncLibrary; +import org.smartregister.chw.anc.domain.MemberObject; import org.smartregister.chw.anc.domain.Visit; import org.smartregister.chw.configs.AllClientsRegisterRowOptions; import org.smartregister.chw.core.application.CoreChwApplication; @@ -678,6 +679,8 @@ public interface Flavor { boolean hideCaregiverAndFamilyHeadWhenOnlyOneAdult(); + int immunizationCeilingMonths(MemberObject memberObject); + boolean hasMap(); boolean showsPhysicallyDisabledView(); diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/application/DefaultChwApplicationFlv.java b/opensrp-chw/src/main/java/org/smartregister/chw/application/DefaultChwApplicationFlv.java index 8bffa092c5..c15ec141ac 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/application/DefaultChwApplicationFlv.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/application/DefaultChwApplicationFlv.java @@ -1,5 +1,6 @@ package org.smartregister.chw.application; +import org.smartregister.chw.anc.domain.MemberObject; import org.smartregister.chw.core.utils.ChildDBConstants; import org.smartregister.chw.core.utils.CoreConstants; import org.smartregister.family.util.DBConstants; @@ -324,6 +325,11 @@ public String[] getFTSTables() { return new String[]{CoreConstants.TABLE_NAME.FAMILY, CoreConstants.TABLE_NAME.FAMILY_MEMBER, CoreConstants.TABLE_NAME.CHILD}; } + @Override + public int immunizationCeilingMonths(MemberObject memberObject) { + return 24; + } + @Override public Map getFTSSearchMap() { Map map = new HashMap<>(); diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/presenter/ChildProfilePresenter.java b/opensrp-chw/src/main/java/org/smartregister/chw/presenter/ChildProfilePresenter.java index 68ee76f89b..6cbe9643cd 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/presenter/ChildProfilePresenter.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/presenter/ChildProfilePresenter.java @@ -14,6 +14,7 @@ import org.smartregister.chw.R; import org.smartregister.chw.activity.ChildProfileActivity; import org.smartregister.chw.activity.ReferralRegistrationActivity; +import org.smartregister.chw.anc.domain.MemberObject; import org.smartregister.chw.application.ChwApplication; import org.smartregister.chw.core.contract.CoreChildProfileContract; import org.smartregister.chw.core.model.ChildVisit; @@ -28,6 +29,7 @@ import org.smartregister.chw.model.ReferralTypeModel; import org.smartregister.chw.util.Constants; import org.smartregister.chw.util.JsonFormUtils; +import org.smartregister.chw.util.UpcomingServicesUtil; import org.smartregister.chw.util.Utils; import org.smartregister.clientandeventmodel.Client; import org.smartregister.clientandeventmodel.Event; @@ -52,6 +54,7 @@ public class ChildProfilePresenter extends CoreChildProfilePresenter { private List referralTypeModels; + private MemberObject childMemberObject = null; public ChildProfilePresenter(CoreChildProfileContract.View childView, CoreChildProfileContract.Flavor flavor, CoreChildProfileContract.Model model, String childBaseEntityId) { super(childView, model, childBaseEntityId); @@ -134,6 +137,7 @@ public void startSickChildForm(CommonPersonObjectClient client) { @Override public void refreshProfileTopSection(CommonPersonObjectClient client, CommonPersonObject familyPersonObject) { super.refreshProfileTopSection(client, familyPersonObject); + childMemberObject = new MemberObject(client); if (ChwApplication.getApplicationFlavor().showLastNameOnChildProfile()) { String relationalId = getValue(client.getColumnmaps(), ChildDBConstants.KEY.RELATIONAL_ID, true).toLowerCase(); @@ -189,7 +193,12 @@ public void updateChildService(CoreChildService childService) { } private void setDueView() { - if (ChwChildDao.hasDueTodayVaccines(childBaseEntityId) || ChwChildDao.hasDueAlerts(childBaseEntityId)) { +// boolean vaccineCardReceived = VisitDao.memberHasVaccineCard(childBaseEntityId); + + if ((childMemberObject != null && getView() != null + && UpcomingServicesUtil.hasUpcomingDueServices(childMemberObject, getView().getContext())) + || ChwChildDao.hasDueTodayVaccines(childBaseEntityId) + || ChwChildDao.hasDueAlerts(childBaseEntityId)) { getView().setVisitButtonDueStatus(); } else { getView().setNoButtonView(); diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/presenter/FamilyProfileDuePresenter.java b/opensrp-chw/src/main/java/org/smartregister/chw/presenter/FamilyProfileDuePresenter.java index f30c8f3693..3942e23960 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/presenter/FamilyProfileDuePresenter.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/presenter/FamilyProfileDuePresenter.java @@ -58,17 +58,16 @@ private String getChildDueQueryForChildrenUnderTwoAndGirlsAgeNineToEleven() { String ageFilter = "(((julianday('now') - julianday(ec_child.dob))/365.25) < 2 or (ec_child.gender = 'Female' and (((julianday('now') - julianday(ec_child.dob))/365.25) BETWEEN 9 AND 11)))\n"; return (ChwApplication.getApplicationFlavor().checkExtraForDueInFamily() ? ageFilter : " (ifnull(schedule_service.completion_date,'') = '' and schedule_service.expiry_date >= strftime('%Y-%m-%d') " + - "and schedule_service.due_date <= strftime('%Y-%m-%d') and ifnull(schedule_service.not_done_date,'') = '' ) " + - "and " + ageFilter); + "and schedule_service.due_date <= strftime('%Y-%m-%d') and ifnull(schedule_service.not_done_date,'') = '' ) " + + "and " + ageFilter); } - private String getSelectCondition(){ + private String getSelectCondition() { String condition = " ( ec_family_member.relational_id = '" + this.familyBaseEntityId + "' or ec_family.base_entity_id = '" + this.familyBaseEntityId + "' ) AND "; - if(ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus()){ + if (ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus()) { condition += getDefaultChildDueQuery(); // + " EXISTS(select * from alerts where caseID = ec_family_member.base_entity_id and status in ('normal','urgent') and expiryDate > date()) AND " - } - else { + } else { condition += getChildDueQueryForChildrenUnderTwoAndGirlsAgeNineToEleven(); // + "EXISTS(select * from alerts where caseID = ec_family_member.base_entity_id and status in ('normal','urgent') and expiryDate > date()) AND " } @@ -76,7 +75,7 @@ private String getSelectCondition(){ return condition + (ChwApplication.getApplicationFlavor().checkExtraForDueInFamily() ? String.format(" and ec_family_member.base_entity_id in (%s)", validMembers()) : ""); } - String validMembers(){ + String validMembers() { List> familyMembers = FamilyMemberDao.getFamilyMembers(this.familyBaseEntityId); StringBuilder joiner = new StringBuilder(); @@ -86,14 +85,16 @@ String validMembers(){ member.setFamilyBaseEntityId(this.familyBaseEntityId); member.setDob(familyMemberRepr.second); - boolean vaccineCardReceived = VisitDao.memberHasVaccineCard(member.getBaseEntityId()); +// boolean vaccineCardReceived = VisitDao.memberHasVaccineCard(member.getBaseEntityId()); + String childGender = ChwChildDao.getChildGender(member.getBaseEntityId()); - if (!vaccineCardReceived || UpcomingServicesUtil.hasUpcomingDueServices(member, contextSupplier.get())) { + if (/*!vaccineCardReceived || */UpcomingServicesUtil.showStatusForChild(member, childGender) + && UpcomingServicesUtil.hasUpcomingDueServices(member, contextSupplier.get())) { joiner.append(String.format("'%s'", member.getBaseEntityId())); joiner.append(","); } } - if(!joiner.toString().equalsIgnoreCase("")){ + if (!joiner.toString().equalsIgnoreCase("")) { joiner.deleteCharAt(joiner.length() - 1); } @@ -108,7 +109,7 @@ public boolean saveDataFamilyKit(String jsonObject) { return familyKitModel.saveFamilyKitEvent(jsonObject); } - static class FamilyMemberDao extends AbstractDao{ + static class FamilyMemberDao extends AbstractDao { public static List> getFamilyMembers(String baseEntityId) { String sql = "SELECT base_entity_id, dob from ec_family_member" + " where relational_id = '" + baseEntityId + "'" + diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/provider/FamilyRegisterProvider.java b/opensrp-chw/src/main/java/org/smartregister/chw/provider/FamilyRegisterProvider.java index cd1eaf6d2f..0b1f236f06 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/provider/FamilyRegisterProvider.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/provider/FamilyRegisterProvider.java @@ -132,6 +132,8 @@ private void updateButtonState(Context context, RegisterViewHolder viewHolder, M setTasksDoneStatus(context, viewHolder.dueButton); } else if (visits_not_done != null && visits_not_done > 0) { setTaskNotDone(context, viewHolder.dueButton); + }else if (due == 0 && over_due == 0){ + viewHolder.dueButton.setVisibility(View.GONE); } } else { diff --git a/opensrp-chw/src/main/java/org/smartregister/chw/util/UpcomingServicesUtil.java b/opensrp-chw/src/main/java/org/smartregister/chw/util/UpcomingServicesUtil.java index 242dd0efff..66a524a112 100644 --- a/opensrp-chw/src/main/java/org/smartregister/chw/util/UpcomingServicesUtil.java +++ b/opensrp-chw/src/main/java/org/smartregister/chw/util/UpcomingServicesUtil.java @@ -7,6 +7,7 @@ import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.LocalDate; +import org.joda.time.Months; import org.smartregister.chw.anc.contract.BaseAncUpcomingServicesContract; import org.smartregister.chw.anc.domain.MemberObject; import org.smartregister.chw.anc.model.BaseUpcomingService; @@ -15,14 +16,20 @@ import org.smartregister.chw.dao.ChwChildDao; import org.smartregister.chw.interactor.ChildUpcomingServiceInteractor; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; +import timber.log.Timber; + public final class UpcomingServicesUtil { static List deepCopy(@Nullable List serviceList) { if (serviceList == null) return null; @@ -32,7 +39,7 @@ static List deepCopy(@Nullable List se for (BaseUpcomingService service : serviceList) { BaseUpcomingService copy = new BaseUpcomingService(); copy.setServiceName(service.getServiceName()); - copy.setServiceDate(service.getOverDueDate()); + copy.setServiceDate(service.getServiceDate()); copy.setExpiryDate(service.getExpiryDate()); copy.setOverDueDate(service.getOverDueDate()); @@ -71,14 +78,29 @@ static String getDueServicesState(List serviceList) { return hasDue ? CoreConstants.VISIT_STATE.DUE : null; } - public static boolean hasUpcomingDueServices(MemberObject memberObject, Context ctx){ - String childGender = ChwChildDao.getChildGender(memberObject.getBaseEntityId()); + public static boolean showStatusForChild(MemberObject memberObject, final String childGender) { int childAge = memberObject.getAge(); - if (!ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus() - && childAge >= 2 - && !(childGender.equalsIgnoreCase("Female") && childAge >= 9 && childAge <= 11)){ - return false; + + return (ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus() && (childAge < 2 || (childGender.equalsIgnoreCase("Female") && childAge >= 9 && childAge <= 11)) + || !ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus()); + } + + static Integer getAgeInMonths(MemberObject memberObject) { + Date dob; + try { + dob = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(memberObject.getDob()); + return Months.monthsBetween(new LocalDate(dob), new LocalDate()).getMonths(); + } catch (ParseException e) { + Timber.e(e); } + return null; + } + + public static boolean hasUpcomingDueServices(MemberObject memberObject, Context ctx) { + Integer monthAge = getAgeInMonths(memberObject); + if (monthAge == null || monthAge >= ChwApplication.getApplicationFlavor().immunizationCeilingMonths(memberObject)) + return false; + List upcomingServices = new ChildUpcomingServiceInteractor().getUpcomingServices(memberObject, ctx); return getDueServicesState(upcomingServices) != null; } @@ -88,7 +110,7 @@ public static void fetchUpcomingDueServicesState(MemberObject memberObject, Cont int childAge = memberObject.getAge(); if (!ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus() && childAge >= 2 - && !(childGender.equalsIgnoreCase("Female") && childAge >= 9 && childAge <= 11)){ + && !(childGender.equalsIgnoreCase("Female") && childAge >= 9 && childAge <= 11)) { String dueStatus = ""; onDueStatusFetched.accept(dueStatus); return; @@ -102,10 +124,10 @@ public void onDataFetched(List serviceList) { }); } - public static void fetchFamilyUpcomingDueServicesState(List memberObjects, Context ctx, Consumer > onFamilyDueStatesConsumer){ + public static void fetchFamilyUpcomingDueServicesState(List memberObjects, Context ctx, Consumer> onFamilyDueStatesConsumer) { Map upcoming = new HashMap<>(); List fetched = new ArrayList<>(); - for (MemberObject member: memberObjects) { + for (MemberObject member : memberObjects) { fetchUpcomingDueServicesState(member, ctx, new Consumer() { @Override public void accept(String s) { @@ -122,7 +144,7 @@ public Integer apply(String s) { } }); fetched.add(s); - if (fetched.size() >= memberObjects.size()){ + if (fetched.size() >= memberObjects.size()) { onFamilyDueStatesConsumer.accept(upcoming); } } diff --git a/opensrp-chw/src/test/java/org/smartregister/chw/application/CoreChwApplicationTest.java b/opensrp-chw/src/test/java/org/smartregister/chw/application/CoreChwApplicationTest.java index 665410ad5c..7436ebbd4b 100644 --- a/opensrp-chw/src/test/java/org/smartregister/chw/application/CoreChwApplicationTest.java +++ b/opensrp-chw/src/test/java/org/smartregister/chw/application/CoreChwApplicationTest.java @@ -5,6 +5,7 @@ import org.mockito.Mockito; import org.robolectric.util.ReflectionHelpers; import org.smartregister.chw.BaseUnitTest; +import org.smartregister.chw.anc.domain.MemberObject; import org.smartregister.immunization.ImmunizationLibrary; import org.smartregister.reporting.ReportingLibrary; @@ -29,4 +30,10 @@ public void testP2PClassifierIsInitialized() { ReflectionHelpers.setField(application, "flavor", flv); Assert.assertNotNull(application.getP2PClassifier()); } + + @Test + public void testApplicationImmunizationCeiling(){ + MemberObject memberObject = Mockito.mock(MemberObject.class); + Assert.assertEquals(24, ChwApplication.getApplicationFlavor().immunizationCeilingMonths(memberObject)); + } } diff --git a/opensrp-chw/src/test/java/org/smartregister/chw/model/FamilyRemoveMemberModelTest.java b/opensrp-chw/src/test/java/org/smartregister/chw/model/FamilyRemoveMemberModelTest.java new file mode 100644 index 0000000000..85f92d6289 --- /dev/null +++ b/opensrp-chw/src/test/java/org/smartregister/chw/model/FamilyRemoveMemberModelTest.java @@ -0,0 +1,36 @@ +package org.smartregister.chw.model; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.smartregister.chw.BaseUnitTest; +import org.smartregister.chw.core.utils.CoreConstants; +import org.smartregister.commonregistry.CommonPersonObjectClient; + +import java.util.ArrayList; +import java.util.List; + +public class FamilyRemoveMemberModelTest extends BaseUnitTest { + + @Mock + private CommonPersonObjectClient personObjectClient; + + private FamilyRemoveMemberModel familyRemoveMemberModel; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + familyRemoveMemberModel = new FamilyRemoveMemberModel(); + } + + @Test + public void testGetValidForm(){ + String form = familyRemoveMemberModel.getForm(personObjectClient); + List validForms = new ArrayList(2); + validForms.add(CoreConstants.JSON_FORM.getFamilyDetailsRemoveMember()); + validForms.add(CoreConstants.JSON_FORM.getFamilyDetailsRemoveChild()); + Assert.assertTrue(validForms.contains(form)); + } +} \ No newline at end of file diff --git a/opensrp-chw/src/test/java/org/smartregister/chw/presenter/ChildProfilePresenterTest.java b/opensrp-chw/src/test/java/org/smartregister/chw/presenter/ChildProfilePresenterTest.java index 7566be691e..856683d7c1 100644 --- a/opensrp-chw/src/test/java/org/smartregister/chw/presenter/ChildProfilePresenterTest.java +++ b/opensrp-chw/src/test/java/org/smartregister/chw/presenter/ChildProfilePresenterTest.java @@ -9,6 +9,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.robolectric.util.ReflectionHelpers; import org.smartregister.chw.BaseUnitTest; import org.smartregister.chw.core.contract.CoreChildProfileContract; import org.smartregister.chw.interactor.ChildProfileInteractor; @@ -98,5 +99,6 @@ public void testRefreshProfileTopSection() { Mockito.verify(view).setProfileName(Mockito.any()); Mockito.verify(view).setAge(Mockito.any()); + Assert.assertNotNull(ReflectionHelpers.getField(profilePresenter, "childMemberObject")); } } diff --git a/opensrp-chw/src/test/java/org/smartregister/chw/util/UpcomingServicesUtilTest.java b/opensrp-chw/src/test/java/org/smartregister/chw/util/UpcomingServicesUtilTest.java new file mode 100644 index 0000000000..cc662339cc --- /dev/null +++ b/opensrp-chw/src/test/java/org/smartregister/chw/util/UpcomingServicesUtilTest.java @@ -0,0 +1,80 @@ +package org.smartregister.chw.util; + +import android.content.Context; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.smartregister.chw.BaseUnitTest; +import org.smartregister.chw.anc.domain.MemberObject; +import org.smartregister.chw.anc.model.BaseUpcomingService; +import org.smartregister.chw.application.ChwApplication; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class UpcomingServicesUtilTest extends BaseUnitTest { + + @Mock + private MemberObject memberObject; + + @Mock + private Context androidContext; + + private final Random random = new Random(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetAgeInMonths(){ + Mockito.when(memberObject.getDob()).thenReturn("2021-07-28"); + Assert.assertNotNull(UpcomingServicesUtil.getAgeInMonths(memberObject)); + } + + @Test + public void testDeepCopyNull(){ + Assert.assertNull(UpcomingServicesUtil.deepCopy(null)); + } + + @Test + public void testDeepCopyReturnsCopy(){ + BaseUpcomingService upcomingService = Mockito.mock(BaseUpcomingService.class); + List baseUpcomingServiceList = new ArrayList<>(); + baseUpcomingServiceList.add(upcomingService); + + List copy = UpcomingServicesUtil.deepCopy(baseUpcomingServiceList); + BaseUpcomingService baseUpcomingService2 = copy.get(0); + + Assert.assertEquals(upcomingService.getServiceName(), baseUpcomingService2.getServiceName()); + Assert.assertEquals(upcomingService.getOverDueDate(), baseUpcomingService2.getOverDueDate()); + Assert.assertEquals(upcomingService.getExpiryDate(), baseUpcomingService2.getExpiryDate()); + Assert.assertEquals(upcomingService.getOverDueDate(), baseUpcomingService2.getServiceDate()); + } + + + @Test + public void testShowStatusForChild(){ + Mockito.when(memberObject.getAge()).thenReturn(random.nextInt(20)); + int age = memberObject.getAge(); + String gender = new String[]{"female", "male"}[random.nextInt(2)]; + boolean expected = (ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus() + && (age < 2 || (gender.equalsIgnoreCase("Female") && age >= 9 && age <= 11)) + || !ChwApplication.getApplicationFlavor().showChildrenAboveTwoDueStatus()); + + Assert.assertEquals(expected, UpcomingServicesUtil.showStatusForChild(memberObject, gender)); + } + + @Test + public void testHasUpcomingServicesForAgeNull(){ + Mockito.when(memberObject.getDob()).thenReturn(""); + Assert.assertNull(UpcomingServicesUtil.getAgeInMonths(memberObject)); + Assert.assertFalse(UpcomingServicesUtil.hasUpcomingDueServices(memberObject, androidContext)); + } +} \ No newline at end of file