Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/org/simple/clinic/feature/Feature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ class PatientSummaryScreen :
override fun createUpdate(): Update<PatientSummaryModel, PatientSummaryEvent, PatientSummaryEffect> {
return PatientSummaryUpdate(
isPatientReassignmentFeatureEnabled = features.isEnabled(Feature.PatientReassignment),
isPatientStatinNudgeEnabled = features.isEnabled(Feature.PatientStatinNudge),
isPatientStatinNudgeV1Enabled = features.isEnabled(Feature.PatientStatinNudge),
isPatientStatinNudgeV2Enabled = features.isEnabled(Feature.PatientStatinNudgeV2),
)
}

Expand Down Expand Up @@ -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) }
)
}
}
Expand Down
34 changes: 12 additions & 22 deletions app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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<PatientSummaryModel, PatientSummaryEvent, PatientSummaryEffect> {

override fun update(
Expand Down Expand Up @@ -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))
}
}

Expand Down Expand Up @@ -369,7 +359,7 @@ class PatientSummaryUpdate(
): Next<PatientSummaryModel, PatientSummaryEffect> {
val effects = mutableSetOf<PatientSummaryEffect>()

if (isPatientStatinNudgeEnabled) {
if (isPatientStatinNudgeV1Enabled || isPatientStatinNudgeV2Enabled) {
effects.add(LoadStatinPrescriptionCheckInfo(patient = event.patientSummaryProfile.patient))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
124 changes: 109 additions & 15 deletions app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ class PatientSummaryUpdateTest {

private val updateSpec = UpdateSpec(PatientSummaryUpdate(
isPatientReassignmentFeatureEnabled = true,
isPatientStatinNudgeEnabled = false,
isPatientStatinNudgeV1Enabled = true,
isPatientStatinNudgeV2Enabled = true,
))

@Test
Expand All @@ -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))
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -2150,25 +2178,31 @@ class PatientSummaryUpdateTest {
),
medicalHistory = TestData.medicalHistory(
hasDiabetes = No,
hasHadStroke = No,
hasHadStroke = Yes,
hasHadHeartAttack = No,
),
prescriptions = listOf(
TestData.prescription(name = "losartin")
),
))
.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(
Expand All @@ -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(
Expand All @@ -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
Expand Down
Loading