Skip to content

Commit

Permalink
Merge branch 'mwcore-dev' into mwcore-p2p-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
LZRS authored Nov 14, 2023
2 parents 1e09d94 + b717981 commit 524bc9f
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 45 deletions.
2 changes: 1 addition & 1 deletion android/engine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ dependencies {
transitive = true
}

api('org.smartregister:engine:0.1.0-beta04-preview4-SNAPSHOT') {
api('org.smartregister:engine:0.1.0-beta04-preview4.1-SNAPSHOT') {
transitive = true
exclude group: 'org.hamcrest', module: 'hamcrest-core'
exclude group: 'javax.xml.bind', module: 'jaxb-api'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@ import androidx.annotation.VisibleForTesting.Companion.PROTECTED
import ca.uhn.fhir.rest.gclient.TokenClientParam
import ca.uhn.fhir.rest.param.ParamPrefixEnum
import com.google.android.fhir.FhirEngine
import com.google.android.fhir.get
import com.google.android.fhir.logicalId
import com.google.android.fhir.search.BaseSearch
import com.google.android.fhir.search.Operation
import com.google.android.fhir.search.Order
import com.google.android.fhir.search.Search
import com.google.android.fhir.search.count
import com.google.android.fhir.search.filter.ReferenceParamFilterCriterion
import com.google.android.fhir.search.filter.TokenParamFilterCriterion
import com.google.android.fhir.search.has
Expand Down Expand Up @@ -99,7 +97,7 @@ constructor(
sharedPreferencesHelper.read<Practitioner>(key = LOGGED_IN_PRACTITIONER, decodeWithGson = true)
}

private fun Search.validTasksFilters() {
private val filtersForValidTask: BaseSearch.() -> Unit = {
filter(
TokenClientParam("_tag"),
{ value = of(tracingCoding) },
Expand Down Expand Up @@ -134,7 +132,7 @@ constructor(

if (page >= 0) from = page * PaginationConstant.DEFAULT_PAGE_SIZE

has<Task>(Task.SUBJECT) { this@search.validTasksFilters() }
has<Task>(Task.SUBJECT) { filtersForValidTask() }

filters.patientCategory?.let {
val paramQueries: List<(TokenParamFilterCriterion.() -> Unit)> =
Expand Down Expand Up @@ -193,7 +191,7 @@ constructor(
if (patientrefs.isNotEmpty()) {
fhirEngine
.search<Task> {
validTasksFilters()
filtersForValidTask()
filter(Task.SUBJECT, *patientrefs, operation = Operation.OR)
}
.map { it.resource }
Expand Down Expand Up @@ -274,7 +272,7 @@ constructor(
): List<RegisterData> {

val tracingPatients =
fhirEngine.search<Patient> { has<Task>(Task.SUBJECT) { this@search.validTasksFilters() } }
fhirEngine.search<Patient> { has<Task>(Task.SUBJECT) { filtersForValidTask() } }

return tracingPatients
.map { it.resource }
Expand Down Expand Up @@ -394,9 +392,9 @@ constructor(

override suspend fun countRegisterData(appFeatureName: String?): Long {
val patients =
fhirEngine
.search<Patient> { has<Task>(Task.SUBJECT) { this@search.validTasksFilters() } }
.map { it.resource }
fhirEngine.search<Patient> { has<Task>(Task.SUBJECT) { filtersForValidTask() } }.map {
it.resource
}
return patients.count { validTasks(it).any() }.toLong()
}

Expand All @@ -407,7 +405,7 @@ constructor(
val patientTasks =
fhirEngine
.search<Task> {
validTasksFilters()
filtersForValidTask()
filter(Task.SUBJECT, { value = patient.referenceValue() })
}
.map { it.resource }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@
package org.smartregister.fhircore.engine.sync

import android.content.Context
import androidx.lifecycle.asFlow
import androidx.work.WorkManager
import androidx.work.hasKeyWithValueOfType
import com.google.android.fhir.FhirEngine
import com.google.android.fhir.sync.FhirSyncWorker
import com.google.android.fhir.sync.ResourceSyncException
import com.google.android.fhir.sync.Sync
import com.google.android.fhir.sync.SyncJobStatus
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.launch
import org.hl7.fhir.r4.model.ResourceType
import org.smartregister.fhircore.engine.R
Expand Down Expand Up @@ -57,6 +67,14 @@ constructor(
val tokenAuthenticator: TokenAuthenticator,
@ApplicationContext val appContext: Context
) {

private inline fun <reified W : FhirSyncWorker> getWorkerInfo(): Flow<SyncJobStatus> {
val oneTimeWorkName = "${W::class.java.name}-oneTimeSync"
val periodicWorkName = "${W::class.java.name}-periodicSync"

return getWorkerInfo(oneTimeWorkName)
}

fun runSync(networkState: (Context) -> Boolean = { NetworkState(it).invoke() }) {
Timber.i("Running one-time sync...")
CoroutineScope(dispatcherProvider.io()).launch {
Expand All @@ -78,7 +96,9 @@ constructor(
sharedSyncStatus.emit(SyncJobStatus.Failed(listOf(authFailResourceSyncException)))
return@launch
}
Sync.oneTimeSync<AppSyncWorker>(appContext).collect {

Sync.oneTimeSync<AppSyncWorker>(appContext)
getWorkerInfo<AppSyncWorker>().collect {
sharedSyncStatus.emit(it)
this@SyncBroadcaster.traceSync(it)
}
Expand Down Expand Up @@ -111,6 +131,28 @@ constructor(
}
}

/**
* Workaround to ensure terminal SyncJobStatus, i.e SyncJobStatus.Failed and
* SyncJobStatus.Finished, get emitted
*
* Gets the worker info for the [FhirSyncWorker], including outputData
*/
@OptIn(ExperimentalCoroutinesApi::class)
private fun getWorkerInfo(workerName: String): Flow<SyncJobStatus> =
WorkManager.getInstance(appContext)
.getWorkInfosForUniqueWorkLiveData(workerName)
.asFlow()
.flatMapConcat { it.asFlow() }
.flatMapConcat { workInfo ->
flowOf(workInfo.progress, workInfo.outputData)
.filter { it.keyValueMap.isNotEmpty() && it.hasKeyWithValueOfType<String>("StateType") }
.mapNotNull {
val state = it.getString("StateType")!!
val stateData = it.getString("State")
Sync.gson.fromJson(stateData, Class.forName(state)) as SyncJobStatus
}
}

companion object {
const val SYNC_TRACE = "runSync"
const val SYNC_GLITCHES_METRIC = "sync_glitches"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ object TracingHelpers {
"art-client-welcome-service-high-or-detectable-viral-load",
"art-client-viral-load-collection",
"exposed-infant-convert-to-art-client",
"patient-finish-visit"
"patient-finish-visit",
"exposed-infant-record-hiv-test-results",
"art-client-child-contact-registration",
"art-client-biological-parent-contact-registration",
"art-client-child-contact-registration",
"art-client-sexual-contact-registration",
"art-client-sibling-contact-registration",
"art-client-social-network-contact-registration"
)
const val tracingBundleId = "tracing"
fun requireTracingTasks(id: String): Boolean =
Expand Down
12 changes: 6 additions & 6 deletions android/quest/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,22 @@ android {
dimension "apps"
applicationIdSuffix ".mwcore"
versionNameSuffix "-mwcore"
versionCode 25
versionName "0.1.15"
versionCode 29
versionName "0.1.19"
}
mwcoreDev {
dimension "apps"
applicationIdSuffix ".mwcoreDev"
versionNameSuffix "-mwcoreDev"
versionCode 25
versionName "0.1.15"
versionCode 29
versionName "0.1.19"
}
mwcoreProd {
dimension "apps"
applicationIdSuffix ".mwcoreProd"
versionNameSuffix "-mwcoreProd"
versionCode 4
versionName "0.0.4"
versionCode 7
versionName "0.0.7"
}
afyayangu {
dimension "apps"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.smartregister.fhircore.quest

import android.accounts.AccountManager
import android.app.Activity
import android.app.Application
import android.content.Context
Expand All @@ -41,7 +42,6 @@ import org.smartregister.fhircore.engine.ui.appsetting.AppSettingActivity
import org.smartregister.fhircore.engine.ui.login.LoginActivity
import org.smartregister.fhircore.engine.ui.questionnaire.QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl
import org.smartregister.fhircore.engine.util.extension.getActivity
import org.smartregister.fhircore.engine.util.extension.launchActivityWithNoBackStackHistory
import org.smartregister.fhircore.engine.util.extension.showToast
import timber.log.Timber

Expand Down Expand Up @@ -147,9 +147,15 @@ class QuestApplication :
name !in activitiesAccessWithoutAuth
}
?.let {
mForegroundActivityContext
?.getActivity()
?.launchActivityWithNoBackStackHistory<LoginActivity>()
mForegroundActivityContext?.getActivity()?.run {
this.startActivity(
Intent(this, LoginActivity::class.java).apply {
accountAuthenticator.retrieveLastLoggedInUsername()?.takeIf { it.isNotBlank() }?.let {
putExtra(AccountManager.KEY_ACCOUNT_NAME, it)
}
}
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import javax.inject.Inject
import javax.inject.Provider
import kotlin.math.ceil
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -64,7 +65,7 @@ class MeasureReportViewModel
@Inject
constructor(
val fhirEngine: FhirEngine,
val fhirOperator: FhirOperator,
val fhirOperator: Provider<FhirOperator>,
val sharedPreferencesHelper: SharedPreferencesHelper,
val dispatcherProvider: DefaultDispatcherProvider,
val measureReportRepository: MeasureReportRepository,
Expand Down Expand Up @@ -210,23 +211,25 @@ constructor(
withContext(dispatcherProvider.io()) {
fhirEngine.loadCqlLibraryBundle(
context = context,
fhirOperator = fhirOperator,
fhirOperator = fhirOperator.get(),
sharedPreferencesHelper = sharedPreferencesHelper,
resourcesBundlePath = measureResourceBundleUrl
)
}
if (reportTypeSelectorUiState.value.patientViewData != null && individualEvaluation) {
val measureReport =
withContext(dispatcherProvider.io()) {
fhirOperator.evaluateMeasure(
measureUrl = measureUrl,
start = startDateFormatted,
end = endDateFormatted,
reportType = SUBJECT,
subject = reportTypeSelectorUiState.value.patientViewData!!.logicalId,
practitioner = loggedInPractitioner?.id,
lastReceivedOn = null // Non-null value not supported yet
)
fhirOperator
.get()
.evaluateMeasure(
measureUrl = measureUrl,
start = startDateFormatted,
end = endDateFormatted,
reportType = SUBJECT,
subject = reportTypeSelectorUiState.value.patientViewData!!.logicalId,
practitioner = loggedInPractitioner?.id,
lastReceivedOn = null // Non-null value not supported yet
)
}

if (measureReport.type == MeasureReport.MeasureReportType.INDIVIDUAL) {
Expand Down Expand Up @@ -262,15 +265,17 @@ constructor(
) {
val measureReport =
withContext(dispatcherProvider.io()) {
fhirOperator.evaluateMeasure(
measureUrl = measureUrl,
start = startDateFormatted,
end = endDateFormatted,
reportType = POPULATION,
subject = null,
practitioner = loggedInPractitioner?.id,
lastReceivedOn = null // Non-null value not supported yet
)
fhirOperator
.get()
.evaluateMeasure(
measureUrl = measureUrl,
start = startDateFormatted,
end = endDateFormatted,
reportType = POPULATION,
subject = null,
practitioner = loggedInPractitioner?.id,
lastReceivedOn = null // Non-null value not supported yet
)
}

measureReportPopulationResults.value = formatPopulationMeasureReport(measureReport)
Expand Down

0 comments on commit 524bc9f

Please sign in to comment.