diff --git a/CHANGELOG.md b/CHANGELOG.md index 15348ca6cb6..42b9e1a6e6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ - Add Current smoker question to patient enrolment and summary screen for statin nudge facilities - Update Statin nudge to show CVD risk +- Add firebase remote config `patient_statin_nudge_v2` to load CVD risk. ## 2024-11-11-9265 diff --git a/app/src/main/java/org/simple/clinic/feature/Feature.kt b/app/src/main/java/org/simple/clinic/feature/Feature.kt index 421cc76d8ca..9b54b9e6f15 100644 --- a/app/src/main/java/org/simple/clinic/feature/Feature.kt +++ b/app/src/main/java/org/simple/clinic/feature/Feature.kt @@ -25,5 +25,6 @@ enum class Feature( NotifyAppUpdateAvailableV2(false, "appupdate_enabled_v2"), OverdueInstantSearch(false, "overdue_instant_search_v2"), PatientReassignment(false, "patient_reassignment_v0"), - PatientStatinNudge(false, "patient_statin_nudge_v0") + PatientStatinNudge(false, "patient_statin_nudge_v0"), + PatientStatinNudgeV2(false, "patient_statin_nudge_v2") } diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt index d5958382506..8fc252f80e3 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt @@ -111,7 +111,7 @@ class NewMedicalHistoryScreen : BaseScreen< override fun defaultModel() = NewMedicalHistoryModel.default( country = country, - showIsSmokingQuestion = features.isEnabled(Feature.PatientStatinNudge) + showIsSmokingQuestion = features.isEnabled(Feature.PatientStatinNudgeV2) ) override fun bindView( diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt index 673bbefe1b3..de892f45987 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt @@ -268,7 +268,8 @@ class PatientSummaryScreen : override fun createUpdate(): Update { return PatientSummaryUpdate( isPatientReassignmentFeatureEnabled = features.isEnabled(Feature.PatientReassignment), - isPatientStatinNudgeEnabled = features.isEnabled(Feature.PatientStatinNudge), + isPatientStatinNudgeV1Enabled = features.isEnabled(Feature.PatientStatinNudge), + isPatientStatinNudgeV2Enabled = features.isEnabled(Feature.PatientStatinNudgeV2), ) } @@ -326,7 +327,7 @@ class PatientSummaryScreen : statinInfo = statinInfo, modifier = Modifier.padding(start = 8.dp, end = 8.dp, top = 8.dp), addSmokingClick = { additionalEvents.notify(AddSmokingClicked) }, - addBMIClick = { additionalEvents.notify(AddBMIClicked) } + addBMIClick = { additionalEvents.notify(AddBMIClicked) } ) } } diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt index bc32a41eaca..2ebe0392991 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -27,7 +27,8 @@ import java.util.UUID class PatientSummaryUpdate( private val isPatientReassignmentFeatureEnabled: Boolean, - private val isPatientStatinNudgeEnabled: Boolean, + private val isPatientStatinNudgeV1Enabled: Boolean, + private val isPatientStatinNudgeV2Enabled: Boolean, ) : Update { override fun update( @@ -125,42 +126,31 @@ class PatientSummaryUpdate( hasStatinsPrescribedAlready.not() return when { - !canPrescribeStatin -> { - val updatedModel = model.updateStatinInfo(StatinInfo(canPrescribeStatin = false)) - next(updatedModel) - } - - event.age < minAgeForStatin -> { + (hasCVD || (hasDiabetes && event.age >= minAgeForStatin)) -> { val updatedModel = model.updateStatinInfo( StatinInfo( - canPrescribeStatin = hasCVD, + canPrescribeStatin = canPrescribeStatin, hasCVD = hasCVD ) ) next(updatedModel) } - event.age > maxAgeForCVDRisk -> { - val updatedModel = model.updateStatinInfo( - StatinInfo( - canPrescribeStatin = hasCVD || hasDiabetes, - hasCVD = hasCVD - ) - ) - next(updatedModel) + event.age in minAgeForStatin..maxAgeForCVDRisk && + canPrescribeStatin && + isPatientStatinNudgeV2Enabled -> { + dispatch(LoadCVDRisk(model.patientUuid)) } - hasCVD || hasDiabetes -> { + else -> { val updatedModel = model.updateStatinInfo( StatinInfo( - canPrescribeStatin = true, - hasCVD = hasCVD + canPrescribeStatin = false, + hasCVD = false ) ) next(updatedModel) } - - else -> dispatch(LoadCVDRisk(model.patientUuid)) } } @@ -369,7 +359,7 @@ class PatientSummaryUpdate( ): Next { val effects = mutableSetOf() - if (isPatientStatinNudgeEnabled) { + if (isPatientStatinNudgeV1Enabled || isPatientStatinNudgeV2Enabled) { effects.add(LoadStatinPrescriptionCheckInfo(patient = event.patientSummaryProfile.patient)) } diff --git a/app/src/main/java/org/simple/clinic/summary/medicalhistory/MedicalHistorySummaryView.kt b/app/src/main/java/org/simple/clinic/summary/medicalhistory/MedicalHistorySummaryView.kt index 3b352dcb672..c7bf414b63c 100644 --- a/app/src/main/java/org/simple/clinic/summary/medicalhistory/MedicalHistorySummaryView.kt +++ b/app/src/main/java/org/simple/clinic/summary/medicalhistory/MedicalHistorySummaryView.kt @@ -107,7 +107,7 @@ class MedicalHistorySummaryView( events = events.ofType(), defaultModel = MedicalHistorySummaryModel.create( patientUuid = screenKey.patientUuid, - showIsSmokingQuestion = features.isEnabled(Feature.PatientStatinNudge) + showIsSmokingQuestion = features.isEnabled(Feature.PatientStatinNudgeV2) ), update = MedicalHistorySummaryUpdate(), init = MedicalHistorySummaryInit(), diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt index 62390925ebd..e0f4a33ff35 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryScreenLogicTest.kt @@ -240,7 +240,11 @@ class PatientSummaryScreenLogicTest { events = uiEvents.ofType(), defaultModel = PatientSummaryModel.from(openIntention, patientUuid), init = PatientSummaryInit(), - update = PatientSummaryUpdate(isPatientReassignmentFeatureEnabled = false, isPatientStatinNudgeEnabled = false), + update = PatientSummaryUpdate( + isPatientReassignmentFeatureEnabled = false, + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = false + ), effectHandler = effectHandler.build(), modelUpdateListener = viewRenderer::render ) diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt index 09a33c85bc9..bc6528af0ef 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -85,7 +85,8 @@ class PatientSummaryUpdateTest { private val updateSpec = UpdateSpec(PatientSummaryUpdate( isPatientReassignmentFeatureEnabled = true, - isPatientStatinNudgeEnabled = false, + isPatientStatinNudgeV1Enabled = true, + isPatientStatinNudgeV2Enabled = true, )) @Test @@ -107,6 +108,12 @@ class PatientSummaryUpdateTest { @Test fun `when the patient summary profile is loaded, then update the UI`() { + val updateSpec = UpdateSpec(PatientSummaryUpdate( + isPatientReassignmentFeatureEnabled = true, + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = false, + )) + updateSpec .given(defaultModel) .whenEvent(PatientSummaryProfileLoaded(patientSummaryProfile)) @@ -117,10 +124,28 @@ class PatientSummaryUpdateTest { } @Test - fun `when the patient summary profile is loaded and statin nudge feature flag is enabled, then update the UI and load statin check info`() { + fun `when the patient summary profile is loaded and statin nudge v1 feature flag is enabled, then update the UI and load statin check info`() { + val updateSpec = UpdateSpec(PatientSummaryUpdate( + isPatientReassignmentFeatureEnabled = true, + isPatientStatinNudgeV1Enabled = true, + isPatientStatinNudgeV2Enabled = false, + )) + + updateSpec + .given(defaultModel) + .whenEvent(PatientSummaryProfileLoaded(patientSummaryProfile)) + .then(assertThatNext( + hasModel(defaultModel.patientSummaryProfileLoaded(patientSummaryProfile)), + hasEffects(LoadStatinPrescriptionCheckInfo(patient = patient)) + )) + } + + @Test + fun `when the patient summary profile is loaded and statin nudge v2 feature flag is enabled, then update the UI and load statin check info`() { val updateSpec = UpdateSpec(PatientSummaryUpdate( isPatientReassignmentFeatureEnabled = true, - isPatientStatinNudgeEnabled = true, + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = true, )) updateSpec @@ -1668,7 +1693,8 @@ class PatientSummaryUpdateTest { fun `when patient reassignment feature is disabled, and patient is not dead, and done is clicked, then load data for done click`() { val updateSpec = UpdateSpec(PatientSummaryUpdate( isPatientReassignmentFeatureEnabled = false, - isPatientStatinNudgeEnabled = false + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = false )) val model = defaultModel .currentFacilityLoaded(facility) @@ -1696,7 +1722,8 @@ class PatientSummaryUpdateTest { fun `when patient reassignment feature is disabled, and patient is not dead, and back is clicked, then load data for back click`() { val updateSpec = UpdateSpec(PatientSummaryUpdate( isPatientReassignmentFeatureEnabled = false, - isPatientStatinNudgeEnabled = false + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = false, )) val model = defaultModel .currentFacilityLoaded(facility) @@ -1724,7 +1751,8 @@ class PatientSummaryUpdateTest { fun `when patient reassignment feature is disabled and measurement warning not now is clicked, then load data for back click`() { val updateSpec = UpdateSpec(PatientSummaryUpdate( isPatientReassignmentFeatureEnabled = false, - isPatientStatinNudgeEnabled = false + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = false )) val model = defaultModel .currentFacilityLoaded(facility) @@ -2110,7 +2138,7 @@ class PatientSummaryUpdateTest { } @Test - fun `when statin prescription check info is loaded and person is below 40, then update the state with false`() { + fun `when statin prescription check info is loaded and person is below 40 without cvd, then update the state with false`() { updateSpec .given(defaultModel) .whenEvent(StatinPrescriptionCheckInfoLoaded( @@ -2137,11 +2165,11 @@ class PatientSummaryUpdateTest { } @Test - fun `when statin prescription check info is loaded and person is above 74, then update the state`() { + fun `when statin prescription check info is loaded and person is below 40 with cvd, then update the state with true`() { updateSpec .given(defaultModel) .whenEvent(StatinPrescriptionCheckInfoLoaded( - age = 75, + age = 39, isPatientDead = false, hasBPRecordedToday = true, assignedFacility = TestData.facility( @@ -2150,7 +2178,7 @@ class PatientSummaryUpdateTest { ), medicalHistory = TestData.medicalHistory( hasDiabetes = No, - hasHadStroke = No, + hasHadStroke = Yes, hasHadHeartAttack = No, ), prescriptions = listOf( @@ -2158,17 +2186,23 @@ class PatientSummaryUpdateTest { ), )) .then(assertThatNext( - hasModel(defaultModel.updateStatinInfo(StatinInfo(canPrescribeStatin = false))), + hasModel(defaultModel.updateStatinInfo(StatinInfo(canPrescribeStatin = true, hasCVD = true))), hasNoEffects() )) } @Test - fun `when statin prescription check info is loaded and has history of cvd or diabetes, then update the state`() { + fun `when statin prescription check info is loaded with phase1 and person is greater than or equal to 40 with diabetes, then update the state with true`() { + val updateSpec = UpdateSpec(PatientSummaryUpdate( + isPatientReassignmentFeatureEnabled = false, + isPatientStatinNudgeV1Enabled = true, + isPatientStatinNudgeV2Enabled = false + )) + updateSpec .given(defaultModel) .whenEvent(StatinPrescriptionCheckInfoLoaded( - age = 50, + age = 40, isPatientDead = false, hasBPRecordedToday = true, assignedFacility = TestData.facility( @@ -2191,11 +2225,17 @@ class PatientSummaryUpdateTest { } @Test - fun `when statin prescription check info is loaded and is eligible for cvd risk, then load cvd risk`() { + fun `when statin prescription check info is loaded with phase2 and person is greater than or equal to 40, then load cvd risk`() { + val updateSpec = UpdateSpec(PatientSummaryUpdate( + isPatientReassignmentFeatureEnabled = false, + isPatientStatinNudgeV1Enabled = false, + isPatientStatinNudgeV2Enabled = true + )) + updateSpec .given(defaultModel) .whenEvent(StatinPrescriptionCheckInfoLoaded( - age = 50, + age = 40, isPatientDead = false, hasBPRecordedToday = true, assignedFacility = TestData.facility( @@ -2217,6 +2257,60 @@ class PatientSummaryUpdateTest { )) } + @Test + fun `when statin prescription check info is loaded and person is above 74, then update the state`() { + updateSpec + .given(defaultModel) + .whenEvent(StatinPrescriptionCheckInfoLoaded( + age = 75, + isPatientDead = false, + hasBPRecordedToday = true, + assignedFacility = TestData.facility( + name = "UHC Simple", + facilityType = "UHC" + ), + medicalHistory = TestData.medicalHistory( + hasDiabetes = No, + hasHadStroke = No, + hasHadHeartAttack = No, + ), + prescriptions = listOf( + TestData.prescription(name = "losartin") + ), + )) + .then(assertThatNext( + hasModel(defaultModel.updateStatinInfo(StatinInfo(canPrescribeStatin = false))), + hasNoEffects() + )) + } + + @Test + fun `when statin prescription check info is loaded and has history of cvd or diabetes, then update the state`() { + updateSpec + .given(defaultModel) + .whenEvent(StatinPrescriptionCheckInfoLoaded( + age = 50, + isPatientDead = false, + hasBPRecordedToday = true, + assignedFacility = TestData.facility( + name = "UHC Simple", + facilityType = "UHC" + ), + medicalHistory = TestData.medicalHistory( + hasDiabetes = Yes, + hasHadStroke = No, + hasHadHeartAttack = No, + ), + prescriptions = listOf( + TestData.prescription(name = "losartin") + ), + )) + .then(assertThatNext( + hasModel(defaultModel.updateStatinInfo(StatinInfo(canPrescribeStatin = true))), + hasNoEffects() + )) + } + @Test fun `when cvd risk is loaded and risk score is not null, then load statin info`() { updateSpec