Skip to content

Commit

Permalink
Merge pull request #76 from d-tree-org/production-release
Browse files Browse the repository at this point in the history
Production release
  • Loading branch information
sevenreup authored Jul 8, 2024
2 parents 5a96be2 + 7db37c6 commit 1ea8c8a
Show file tree
Hide file tree
Showing 44 changed files with 983 additions and 317 deletions.
8 changes: 4 additions & 4 deletions android/dataclerk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ android {
dimension = "apps"
applicationIdSuffix = ".exposedInfant"
versionNameSuffix = "-exposedInfant"
versionCode = 3
versionName = "0.0.3"
versionCode = 4
versionName = "0.0.4"
}
create("artClient") {
dimension = "apps"
applicationIdSuffix = ".artClient"
versionNameSuffix = "-artClient"
versionCode = 3
versionName = "0.0.3"
versionCode = 4
versionName = "0.0.4"
}
create("exposedInfantDev") {
dimension = "apps"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject
import org.dtree.fhircore.dataclerk.data.QuestXFhirQueryResolver
import org.smartregister.fhircore.engine.data.remote.fhir.resource.ReferenceUrlResolver
import org.smartregister.fhircore.engine.trace.ReleaseTree
import org.smartregister.fhircore.engine.ui.questionnaire.QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl
import org.smartregister.fhircore.engine.ui.questionnaire.items.CustomQuestItemDataProvider
import timber.log.Timber
Expand All @@ -53,6 +54,8 @@ class DataClerkApplication : Application(), DataCaptureConfig.Provider, Configur
Firebase.crashlytics.setCrashlyticsCollectionEnabled(false)
Firebase.analytics.setAnalyticsCollectionEnabled(false)
Timber.plant(Timber.DebugTree())
} else {
Timber.plant(ReleaseTree())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class PatientPagingSource(private val dataStore: AppDataStore) : PagingSource<In
nextKey = nextPage,
)
} catch (e: Exception) {
Timber.e(e)
LoadResult.Error(e)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import org.dtree.fhircore.dataclerk.util.getFormattedAge
import org.smartregister.fhircore.engine.ui.questionnaire.QuestionnaireActivity
import org.smartregister.fhircore.engine.ui.questionnaire.QuestionnaireType
import org.smartregister.fhircore.engine.util.extension.toHumanDisplay
import timber.log.Timber

@HiltViewModel
class PatientViewModel
Expand Down Expand Up @@ -131,6 +132,7 @@ constructor(
screenState.emit(PatientDetailScreenState.Success(patient, data))
fetchResources(hashList)
} catch (e: Exception) {
Timber.e(e)
screenState.emit(PatientDetailScreenState.Error(e.message ?: "Error"))
}
}
Expand All @@ -153,6 +155,7 @@ constructor(
this[resourceId] = MutableStateFlow(ResourcePropertyState.Success(resource))
}
} catch (e: Exception) {
Timber.e(e)
resourceMapStatus.value =
resourceMapStatus.value.toMutableMap().apply {
this[resourceId] = MutableStateFlow(ResourcePropertyState.Error(e.message ?: "Error"))
Expand Down
7 changes: 3 additions & 4 deletions android/engine/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ dependencies {
exclude(group = "com.google.android.fhir", module = "common")
exclude(group = "com.google.android.fhir", module = "engine")
}
api("org.smartregister:data-capture:1.1.0-preview8.1-SNAPSHOT") {
api("org.smartregister:data-capture:1.1.0-preview11-SNAPSHOT") {
isTransitive = true
exclude(group = "ca.uhn.hapi.fhir")
exclude(group = "com.google.android.fhir", module = "engine")
Expand All @@ -195,9 +195,7 @@ dependencies {

api("org.smartregister:common:0.1.0-alpha05-preview3-SNAPSHOT") { isTransitive = true }

// api("org.smartregister:engine:1.0.0-preview7.1-SNAPSHOT") {
api("org.smartregister:engine:1.0.0-preview8-PERF-TEST-SNAPSHOT") {
// api("org.smartregister:engine:1.0.0-preview7.1-PERF-TEST5-SNAPSHOT") {
api("org.smartregister:engine:1.0.0-preview11-MWCore-SNAPSHOT") {
isTransitive = true
exclude(group = "com.google.android.fhir", module = "common")
exclude(group = "com.github.ben-manes.caffeine")
Expand All @@ -224,6 +222,7 @@ dependencies {
implementation("com.google.firebase:firebase-analytics")

implementation("androidx.core:core-splashscreen:1.0.1")
implementation("me.zhanghai.compose.preference:library:1.0.0")

// Hilt test dependencies
testImplementation("com.google.dagger:hilt-android-testing:${Deps.versions.hiltVersion}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.smartregister.fhircore.engine.ui.questionnaire.QuestionnaireConfig
import org.smartregister.fhircore.engine.util.DispatcherProvider
import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
import org.smartregister.fhircore.engine.util.extension.decodeJson
import timber.log.Timber

/**
* A configuration store used to store all the application configurations. Application
Expand Down Expand Up @@ -63,6 +64,7 @@ constructor(
applicationConfiguration.update { config }
true
} catch (ex: ResourceNotFoundException) {
Timber.e(ex)
false
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.engine.configuration.preferences

enum class SyncUploadStrategy {
Default,
Batch,
Single,
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package org.smartregister.fhircore.engine.data.domain.util

import androidx.paging.PagingSource
import androidx.paging.PagingState
import timber.log.Timber

/**
* Subclass of [PagingSource] that is used to paginate data on the register. Requires
Expand Down Expand Up @@ -64,8 +65,9 @@ class PaginatedDataSource<I : Any, O : Any>(
}

LoadResult.Page(data = data, prevKey = prevKey, nextKey = null)
} catch (exception: Exception) {
LoadResult.Error(exception)
} catch (e: Exception) {
Timber.e(e)
LoadResult.Error(e)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package org.smartregister.fhircore.engine.data.local.purger

import com.google.android.fhir.FhirEngine
import com.google.android.fhir.datacapture.extensions.logicalId
import com.google.android.fhir.search.Operation
import com.google.android.fhir.search.Search
import com.google.android.fhir.search.filter.ReferenceParamFilterCriterion
import com.google.android.fhir.search.search
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
Expand All @@ -30,7 +30,6 @@ import org.hl7.fhir.r4.model.AuditEvent
import org.hl7.fhir.r4.model.CarePlan
import org.hl7.fhir.r4.model.Encounter
import org.hl7.fhir.r4.model.Observation
import org.hl7.fhir.r4.model.Patient
import org.hl7.fhir.r4.model.QuestionnaireResponse
import org.hl7.fhir.r4.model.Resource
import org.hl7.fhir.r4.model.ResourceType
Expand All @@ -50,13 +49,15 @@ class ResourcePurger(private val fhirEngine: FhirEngine) {
onPurgeAppointment()
}

private suspend fun <R : Resource> query(type: ResourceType): Flow<List<R>> = flow {
private suspend fun <R : Resource> query(
type: ResourceType,
query: (Search.() -> Unit)? = null,
): Flow<List<R>> = flow {
var start = 0
do {
val resources =
fhirEngine.search<R>(Search(type, count = PAGE_COUNT, from = PAGE_COUNT * start++)).map {
it.resource
}
val search = Search(type, count = PAGE_COUNT, from = PAGE_COUNT * start++)
query?.let { search.it() }
val resources = fhirEngine.search<R>(search).map { it.resource }
emit(resources)
} while (resources.isNotEmpty())
}
Expand All @@ -69,7 +70,7 @@ class ResourcePurger(private val fhirEngine: FhirEngine) {
fhirEngine.purge(this.resourceType, logicalId)
Timber.tag("purge").d("Purged $resourceType with id: $logicalId")
} catch (e: Exception) {
Timber.tag("purge:Exception").e(e.message!!)
Timber.tag("purge:Exception").e(e)
}

private suspend fun Iterable<Resource>.purge() = this.forEach { it.purge() }
Expand Down Expand Up @@ -104,73 +105,40 @@ class ResourcePurger(private val fhirEngine: FhirEngine) {
.purge()
}

/** Purge Inactive [CarePlan] together with it's associated [Task] */
private suspend fun onPurgeInActiveCarePlanWithTasks(carePlans: List<CarePlan>) =
carePlans
.filter { it.status != CarePlan.CarePlanStatus.ACTIVE }
.also { onPurgeCarePlanWithAssociatedTask(it, false) }

/** Purge Multiple [CarePlan.CarePlanStatus.ACTIVE] together with it's associated [Task] */
private suspend fun onPurgeMultipleActiveCarePlanWithTasks(carePlans: List<CarePlan>) =
carePlans
.filter { it.status == CarePlan.CarePlanStatus.ACTIVE }
.sortedBy { it.meta.lastUpdated }
.also { if (it.size > 1) onPurgeCarePlanWithAssociatedTask(it.subList(1, it.size), true) }

// TODO: Filter out the care_plans in the query before hand
private suspend fun onPurgeCarePlans() {
query<Patient>(ResourceType.Patient)
.filter { it.isNotEmpty() }
.collect { patients ->
val patientIdsReferenceParamFilterCriteria =
patients.map(Patient::logicalId).chunked(50) {
it.map<String, ReferenceParamFilterCriterion.() -> Unit> {
return@map { value = "${ResourceType.Patient.name}/$it" }
}
}
val carePlans = mutableListOf<CarePlan>()
patientIdsReferenceParamFilterCriteria.forEach {
fhirEngine
.search<CarePlan> { filter(CarePlan.SUBJECT, *it.toTypedArray()) }
.map { it.resource }
.let { carePlans.addAll(it) }
}

carePlans
.groupBy { it.subject.reference }
.values
.filter { it.size > 1 }
.forEach {
onPurgeInActiveCarePlanWithTasks(it)
onPurgeMultipleActiveCarePlanWithTasks(it)
}
query<CarePlan>(ResourceType.CarePlan) {
filter(
CarePlan.STATUS,
{ value = of(CarePlan.CarePlanStatus.REVOKED.toCode()) },
{ value = of(CarePlan.CarePlanStatus.ENTEREDINERROR.toCode()) },
{ value = of(CarePlan.CarePlanStatus.COMPLETED.toCode()) },
{ value = of(CarePlan.CarePlanStatus.UNKNOWN.toCode()) },
operation = Operation.OR,
)
}
.collect { carePlans ->
onPurgeCarePlanWithAssociatedTask(
carePlans.filter {
it.status != CarePlan.CarePlanStatus.ACTIVE &&
it.status != CarePlan.CarePlanStatus.ONHOLD &&
it.status != CarePlan.CarePlanStatus.DRAFT
},
)
}
}

private suspend fun onPurgeCarePlanWithAssociatedTask(
carePlans: List<CarePlan>,
isError: Boolean = false,
) {
if (isError) {
// TODO: Should we also update the task statuses?
carePlans.setStatusEnteredInError()
} else {
carePlans
.asSequence()
.flatMap { it.activity }
.mapNotNull { it.outcomeReference.firstOrNull() }
.map { it.reference.substringAfter("/") }
.toSet()
.map { Task().apply { id = it } }
.toList()
.purge()
carePlans.purge()
}
}

private suspend fun Iterable<CarePlan>.setStatusEnteredInError() {
val updateCarePlans = this.map { it.setStatus(CarePlan.CarePlanStatus.ENTEREDINERROR) }
fhirEngine.update(*updateCarePlans.toTypedArray())
private suspend fun onPurgeCarePlanWithAssociatedTask(carePlans: List<CarePlan>) {
carePlans
.asSequence()
.flatMap { it.activity }
.mapNotNull { it.outcomeReference.firstOrNull() }
.map { it.reference.substringAfter("/") }
.toSet()
.map { Task().apply { id = it } }
.toList()
.purge()
carePlans.purge()
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import java.util.Date
import kotlin.math.max
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import org.hl7.fhir.r4.model.Appointment
import org.hl7.fhir.r4.model.CarePlan
import org.hl7.fhir.r4.model.CodeType
import org.hl7.fhir.r4.model.Coding
Expand Down Expand Up @@ -315,7 +314,9 @@ abstract class TracingRegisterDao(
val tasks = validTasks(patient)

val attempt = tracingRepository.getTracingAttempt(patient, tasks)
var dueData = getDueDate(it)
val carePlans = patient.activeCarePlans()

var dueData = carePlans.firstOrNull()?.period?.end

if (dueData == null) {
tasks.minOfOrNull { task -> task.authoredOn }?.let { date -> dueData = date }
Expand All @@ -338,7 +339,7 @@ abstract class TracingRegisterDao(
showIdentifierInProfile = true,
healthStatus = patient.extractHealthStatusFromMeta(metaCodingSystemTag),
tasks = tasks,
services = patient.activeCarePlans(),
services = carePlans,
conditions = defaultRepository.activePatientConditions(patient.logicalId),
guardians = patient.guardians(),
practitioners = patient.practitioners(),
Expand All @@ -351,21 +352,6 @@ abstract class TracingRegisterDao(
}
}

private suspend fun getDueDate(patient: Patient): Date? {
val appointments =
fhirEngine
.fetch<Appointment> {
filter(Appointment.STATUS, { value = of(Appointment.AppointmentStatus.BOOKED.toCode()) })
filter(Appointment.ACTOR, { value = patient.referenceValue() })
sort(Appointment.DATE, Order.ASCENDING)
count = 1
from = 0
}
.map { it.resource }
val appointment = appointments.firstOrNull()
return appointment?.start
}

suspend fun Patient.activeCarePlans() =
defaultRepository
.searchResourceFor<CarePlan>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class TracingRepository @Inject constructor(val fhirEngine: FhirEngine) {
}
}
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
}
}

Expand Down Expand Up @@ -318,7 +318,7 @@ class TracingRepository @Inject constructor(val fhirEngine: FhirEngine) {
encounters.add(resource)
}
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
}
}

Expand Down
Loading

0 comments on commit 1ea8c8a

Please sign in to comment.