From df638ccc23fd6a5bb12548ef998756d71e68d77b Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Thu, 3 Sep 2026 10:57:45 +0530 Subject: [PATCH 1/4] Fix crashes in patient summary and assigned facility (#5918) --- CHANGELOG.md | 6 +++++- .../clinic/summary/PatientSummaryEffect.kt | 4 +++- .../summary/PatientSummaryEffectHandler.kt | 19 ++++++------------- .../clinic/summary/PatientSummaryUpdate.kt | 8 ++++---- .../AssignedFacilityEffectHandler.kt | 9 ++++++--- .../PatientSummaryEffectHandlerTest.kt | 9 +++++---- .../summary/PatientSummaryUpdateTest.kt | 9 +++++---- .../AssignedFacilityEffectHandlerTest.kt | 18 ++++++++++++++++++ 8 files changed, 52 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 703633881bb..9d41367504b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,12 +23,16 @@ - Update GH Actions `setup-jdk` to v6 - Replaced deprecated Gradle Kotlin DSL by project property delegates with explicit project.property(...) access to improve Gradle 10 compatibility. - ### Changes - Enabled CDSS nudges for all countries, previously limited to Sri Lanka and Ethiopia. - Applied the lower blood pressure threshold of 130/80 for diabetic patients in Sri Lanka. +### Fixes + +- Fixed a crash when loading statin information for a patient. +- Fixed a crash when loading the patient's assigned facility. + ## 2026.08.31 ### Internal diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt index b3379b7ddfa..e4561d353eb 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt @@ -83,7 +83,9 @@ data class UpdateCVDRisk( val newRiskRange: CVDRiskRange ) : PatientSummaryEffect() -data class LoadStatinInfo(val patientUuid: UUID) : PatientSummaryEffect() +data class LoadStatinInfo( + val patient: Patient +) : PatientSummaryEffect() data class LoadCVDRiskInfo(val patientUuid: UUID) : PatientSummaryEffect() diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt index 0b6ce697229..f25d7ca35f2 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt @@ -307,14 +307,13 @@ class PatientSummaryEffectHandler @AssistedInject constructor( effects .observeOn(schedulersProvider.io()) .map { effect -> - val patientUuid = effect.patientUuid - val patient = patientRepository.patientImmediate(patientUuid) + val patient = effect.patient val medicalHistory = medicalHistoryRepository.historyForPatientOrDefaultImmediate( defaultHistoryUuid = uuidGenerator.v4(), - patientUuid = patientUuid + patientUuid = patient.uuid ) - val patientAttribute = patientAttributeRepository.getPatientAttributeImmediate(patientUuid) - val riskRange = cvdRiskRepository.getCVDRiskImmediate(patientUuid)?.riskScore + val patientAttribute = patientAttributeRepository.getPatientAttributeImmediate(patient.uuid) + val riskRange = cvdRiskRepository.getCVDRiskImmediate(patient.uuid)?.riskScore val canPrescribeStatin = if (country.isoCountryCode == Country.SRI_LANKA) { riskRange?.canPrescribeStatinInSriLanka ?: false } else { @@ -322,7 +321,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor( } StatinInfoLoaded( - age = patient!!.ageDetails.estimateAge(userClock), + age = patient.ageDetails.estimateAge(userClock), medicalHistory = medicalHistory, canPrescribeStatin = canPrescribeStatin, riskRange = riskRange, @@ -523,12 +522,6 @@ class PatientSummaryEffectHandler @AssistedInject constructor( .flatMap(Function { facilityRepository.facility(it) }) } - private fun getAssignedFacility(assignedFacilityId: UUID?): Optional { - return Optional - .ofNullable(assignedFacilityId) - .flatMap { facilityRepository.facility(it) } - } - private fun mapPatientProfileToSummaryProfile( patientProfile: PatientProfile, facility: Optional @@ -564,7 +557,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor( missingPhoneReminderRepository .markReminderAsShownFor(effect.patientUuid) .subscribeOn(scheduler) - .andThen(Observable.empty()) + .andThen(Observable.empty()) } } } 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 3e63d1d16b6..f914fa417cc 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -106,7 +106,7 @@ class PatientSummaryUpdate( is HypertensionNotNowClicked -> hypertensionNotNowClicked(event.continueToDiabetesDiagnosisWarning) is StatinPrescriptionCheckInfoLoaded -> statinPrescriptionCheckInfoLoaded(event, model) is CVDRiskCalculated -> saveOrUpdateCVDRisk(event, model) - is CVDRiskUpdated -> dispatch(LoadStatinInfo(model.patientUuid)) + is CVDRiskUpdated -> dispatch(LoadStatinInfo(model.patientSummaryProfile!!.patient)) is StatinInfoLoaded -> statinInfoLoaded(event, model) is AddTobaccoUseClicked -> dispatch(ShowTobaccoStatusDialog) is TobaccoUseAnswered -> dispatch(UpdateTobaccoUse(model.patientUuid, event.isSmoker, event.isUsingSmokelessTobacco)) @@ -237,7 +237,7 @@ class PatientSummaryUpdate( } isEligibleForLabBasedCvdRisk -> { - dispatch(LoadStatinInfo(model.patientUuid)) + dispatch(LoadStatinInfo(model.patientSummaryProfile!!.patient)) } else -> { @@ -294,7 +294,7 @@ class PatientSummaryUpdate( } isEligibleForNonLabBasedCvdRisk -> { - dispatch(LoadStatinInfo(model.patientUuid)) + dispatch(LoadStatinInfo(model.patientSummaryProfile!!.patient)) } else -> { @@ -314,7 +314,7 @@ class PatientSummaryUpdate( model: PatientSummaryModel ): Next { return when { - event.newRiskRange == null -> dispatch(LoadStatinInfo(model.patientUuid)) + event.newRiskRange == null -> dispatch(LoadStatinInfo(model.patientSummaryProfile!!.patient)) event.oldRisk != null -> dispatch(UpdateCVDRisk(event.oldRisk, event.newRiskRange)) else -> dispatch(SaveCVDRisk(model.patientUuid, event.newRiskRange)) } diff --git a/app/src/main/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandler.kt b/app/src/main/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandler.kt index d4d65abdf63..fbaad861bcf 100644 --- a/app/src/main/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandler.kt +++ b/app/src/main/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandler.kt @@ -36,7 +36,7 @@ class AssignedFacilityEffectHandler @AssistedInject constructor( return ObservableTransformer { effects -> effects .observeOn(schedulersProvider.io()) - .map { (patientUuid, assignedFacilityId) -> + .doOnNext { (patientUuid, assignedFacilityId) -> patientRepository.updateAssignedFacilityId(patientUuid, assignedFacilityId) } .map { AssignedFacilityChanged } @@ -47,8 +47,11 @@ class AssignedFacilityEffectHandler @AssistedInject constructor( return ObservableTransformer { effects -> effects .observeOn(schedulersProvider.io()) - .map { patientRepository.patientImmediate(it.patientUuid) } - .map(::getAssignedFacility) + .map { effect -> + patientRepository.patientImmediate(effect.patientUuid) + ?.let(::getAssignedFacility) + ?: Optional.empty() + } .map(::AssignedFacilityLoaded) } } diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt index 9c7803e7ad4..cd50454aaec 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt @@ -988,9 +988,7 @@ class PatientSummaryEffectHandlerTest { @Test fun `when load statin info effect is received, then load statin info`() { //given - val bmiReading = BMIReading(height = 177f, weight = 53f) - - whenever(patientRepository.patientImmediate(patientUuid)) doReturn TestData.patient( + val patient = TestData.patient( uuid = patientUuid, patientAgeDetails = PatientAgeDetails( ageValue = 55, @@ -998,6 +996,9 @@ class PatientSummaryEffectHandlerTest { dateOfBirth = null, ) ) + val bmiReading = BMIReading(height = 177f, weight = 53f) + + whenever(patientRepository.patientImmediate(patientUuid)) doReturn patient val medicalHistory = TestData.medicalHistory(isSmoking = Yes) whenever(medicalHistoryRepository.historyForPatientOrDefaultImmediate( @@ -1012,7 +1013,7 @@ class PatientSummaryEffectHandlerTest { TestData.cvdRisk(riskScore = CVDRiskRange(27, 27)) //when - testCase.dispatch(LoadStatinInfo(patientUuid)) + testCase.dispatch(LoadStatinInfo(patient)) //then testCase.assertOutgoingEvents(StatinInfoLoaded( 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 6e3a7c7d748..ea34beab6ae 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -2463,7 +2463,7 @@ class PatientSummaryUpdateTest { )) .then(assertThatNext( hasNoModel(), - hasEffects(LoadStatinInfo(patientUuid)) + hasEffects(LoadStatinInfo(model.patientSummaryProfile!!.patient)) )) } @@ -2496,14 +2496,15 @@ class PatientSummaryUpdateTest { @Test fun `when cvd risk score is calculated and both range and old cvd risk are null, then load statin info`() { + val model = defaultModel.patientSummaryProfileLoaded(patientSummaryProfile) updateSpec - .given(defaultModel) + .given(model) .whenEvent(CVDRiskCalculated( oldRisk = null, newRiskRange = null )) .then(assertThatNext( - hasEffects(LoadStatinInfo(defaultModel.patientUuid)) + hasEffects(LoadStatinInfo(model.patientSummaryProfile!!.patient)) )) } @@ -2995,7 +2996,7 @@ class PatientSummaryUpdateTest { )) .then(assertThatNext( hasNoModel(), - hasEffects(LoadStatinInfo(patientUuid)) + hasEffects(LoadStatinInfo(model.patientSummaryProfile!!.patient)) )) } diff --git a/app/src/test/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandlerTest.kt index 273c17c4d8f..da96f6468b4 100644 --- a/app/src/test/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandlerTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/assignedfacility/AssignedFacilityEffectHandlerTest.kt @@ -90,4 +90,22 @@ class AssignedFacilityEffectHandlerTest { verify(uiActions).notifyAssignedFacilityChanged() verifyNoMoreInteractions(uiActions) } + + @Test + fun `when load assigned facility effect is received and patient is not found, then assigned facility is empty`() { + // given + val patientUuid = UUID.fromString("17bb9690-9a17-4d90-a45f-8bfdcc4153e4") + + whenever(patientRepository.patientImmediate(patientUuid)) doReturn null + + // when + effectHandlerTestCase.dispatch(LoadAssignedFacility(patientUuid)) + + // then + effectHandlerTestCase.assertOutgoingEvents( + AssignedFacilityLoaded(Optional.empty()) + ) + + verifyNoInteractions(uiActions) + } } From de30ff7193692bbc94b8941cec0dbd6b9fe2458c Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Thu, 3 Sep 2026 14:56:40 +0530 Subject: [PATCH 2/4] Update CHANGELOG (#5920) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d41367504b..3db8ea96cb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -## Next Release +## 2026.09.03 ### Internal From 4d64c5cb2dc39879e473f895c2739ba8fe8943b7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 09:50:34 +0000 Subject: [PATCH 3/4] Update agp to v9.4.0 (#5913) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [com.android.lint](https://developer.android.com/studio/build) ([source](https://android.googlesource.com/platform/tools/base)) | `9.3.2` → `9.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.lint:com.android.lint.gradle.plugin/9.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.lint:com.android.lint.gradle.plugin/9.3.2/9.4.0?slim=true) | | [com.android.library](https://developer.android.com/studio/build) ([source](https://android.googlesource.com/platform/tools/base)) | `9.3.2` → `9.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.library:com.android.library.gradle.plugin/9.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.library:com.android.library.gradle.plugin/9.3.2/9.4.0?slim=true) | | [com.android.application](https://developer.android.com/studio/build) ([source](https://android.googlesource.com/platform/tools/base)) | `9.3.2` → `9.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.application:com.android.application.gradle.plugin/9.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.application:com.android.application.gradle.plugin/9.3.2/9.4.0?slim=true) | --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/simpledotorg/simple-android). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: sagarwal --- CHANGELOG.md | 6 ++++++ gradle/libs.versions.toml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db8ea96cb9..103c7623373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## Next Release + +### Internal + +- Bump AGP to v9.4.0 + ## 2026.09.03 ### Internal diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b665d057efe..73a1c19cb3b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "9.3.2" +agp = "9.4.0" androidx-cameraView = "1.6.2" androidx-camera = "1.6.2" From 8d8d1259e6ed57c8605ab29b65eb4325803cab93 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 10:13:38 +0000 Subject: [PATCH 4/4] Update lint to v32.4.0 (#5914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [com.android.tools.lint:lint-tests](http://tools.android.com/) ([source](https://android.googlesource.com/platform/tools/base)) | `32.3.2` → `32.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.tools.lint:lint-tests/32.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.tools.lint:lint-tests/32.3.2/32.4.0?slim=true) | | [com.android.tools.lint:lint](http://tools.android.com/) ([source](https://android.googlesource.com/platform/tools/base)) | `32.3.2` → `32.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.tools.lint:lint/32.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.tools.lint:lint/32.3.2/32.4.0?slim=true) | | [com.android.tools.lint:lint-checks](http://tools.android.com/) ([source](https://android.googlesource.com/platform/tools/base)) | `32.3.2` → `32.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.tools.lint:lint-checks/32.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.tools.lint:lint-checks/32.3.2/32.4.0?slim=true) | | [com.android.tools.lint:lint-api](http://tools.android.com/) ([source](https://android.googlesource.com/platform/tools/base)) | `32.3.2` → `32.4.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.tools.lint:lint-api/32.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.tools.lint:lint-api/32.3.2/32.4.0?slim=true) | --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/simpledotorg/simple-android). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: sagarwal --- CHANGELOG.md | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 103c7623373..e35bfc88924 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Internal - Bump AGP to v9.4.0 +- Bump Lint to v32.4.0 ## 2026.09.03 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 73a1c19cb3b..2cbd5af4fcf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ ksp = "2.3.11" ktlint = "0.36.0" -lint = "32.3.2" +lint = "32.4.0" mobius = "2.1.2"