Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configs Versioning #3189

Merged
merged 54 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
dfe5dc2
Configs versioning setup
qiarie Mar 27, 2024
185ad20
init implementation guide version in settings screen
hilpitome Mar 27, 2024
0d4eb9d
remove unused tag
hilpitome Mar 27, 2024
ce8a916
add string resource
hilpitome Apr 2, 2024
2a5fed4
fetch composition referenced in IG
hilpitome Apr 4, 2024
9a92ce2
add implementationguide to test
hilpitome Apr 4, 2024
5121273
Merge remote-tracking branch 'origin/main' into 3150-configs-versioning
qiarie Apr 5, 2024
4636004
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
qiarie Apr 5, 2024
d53dd8d
Add ImplementationGuide resource
qiarie Apr 5, 2024
0c60abf
update tests
hilpitome Apr 5, 2024
0be0dcd
Merge branch '3151-add-ig-version-to-setting-scrn' into 3150-configs-…
hilpitome Apr 8, 2024
e0f731f
Update implementation_guide_config.json
qiarie Apr 9, 2024
95aa53d
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
qiarie Apr 9, 2024
c2af26e
Refactor flow
qiarie Apr 9, 2024
3b43cbf
Rename implementationGuideUrl to implementationGuideId
qiarie Apr 9, 2024
769426c
Format implementation_guide_config.json
qiarie Apr 9, 2024
ba9c4e6
Run spotlessApply
qiarie Apr 9, 2024
eae2b44
Remove implementationGuideId entry from app config
qiarie Apr 12, 2024
6b16af9
Refactor implementation from config registry
qiarie Apr 12, 2024
e3a3487
refactor to use IG by version
hilpitome Apr 15, 2024
44445c7
Run spotlessApply
qiarie Apr 15, 2024
7679490
Refactors and bug fixes
qiarie Apr 15, 2024
cab32a7
Update sample ImplementationGuide URL and version
qiarie Apr 15, 2024
33a6dfd
Update fetchRemoteIG app URL
qiarie Apr 15, 2024
9a09a85
Merge branch 'main' into 3150-configs-versioning
dubdabasoduba Apr 16, 2024
6c25e42
Remove flavour from versionName when fetching IG
qiarie Apr 17, 2024
3adbb9c
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
qiarie Apr 17, 2024
a7d1238
Merge remote-tracking branch 'origin/main' into 3150-configs-versioning
qiarie Apr 17, 2024
6b1ee83
Save IG after fetch
qiarie Apr 17, 2024
83e0221
Merge branch 'main' into 3150-configs-versioning
pld Apr 17, 2024
6733502
save ImplementationGuide to database
hilpitome Apr 18, 2024
26ccfc9
introduce fetchConfiguration IG test skeletons
hilpitome Apr 18, 2024
adfde26
fix merge conflict
hilpitome Apr 18, 2024
afc344c
Update IG URL to FQDN
qiarie Apr 23, 2024
b3ce06f
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
qiarie Apr 23, 2024
a84a4d6
Merge branch 'main' into 3150-configs-versioning
hilpitome Apr 24, 2024
c885bc8
find and sort IG by context-quantity
hilpitome Apr 24, 2024
6b082b9
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
hilpitome Apr 24, 2024
da10de2
fix failing tests
hilpitome Apr 24, 2024
4577948
update IG tests
hilpitome Apr 25, 2024
50d3bb0
use implmentaionGuide extension guide
hilpitome Apr 25, 2024
172a7bd
use version code for context-quantity
hilpitome Apr 29, 2024
61dcb94
empty commit to trigger checks
hilpitome Apr 29, 2024
21c4794
run spotlessApply
hilpitome Apr 29, 2024
d39a03b
Merge branch 'main' into 3150-configs-versioning
hilpitome May 2, 2024
ec2b1c4
remove unnecessary implementationGuide details from userSettingsScreen
hilpitome May 2, 2024
731373e
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
hilpitome May 2, 2024
74f4e2b
spotlessApply
hilpitome May 2, 2024
bc71d9f
Merge branch 'main' into 3150-configs-versioning
pld May 3, 2024
5777967
initiate Implementation Guide documentation
hilpitome May 6, 2024
68996a1
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
hilpitome May 6, 2024
552b9b0
Update strings.xml
hilpitome May 6, 2024
449a556
Merge branch '3150-configs-versioning' of github.com:opensrp/fhircore…
hilpitome May 6, 2024
0486c22
Merge branch 'main' into 3150-configs-versioning
hilpitome May 6, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.hl7.fhir.r4.model.Binary
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.Composition
import org.hl7.fhir.r4.model.ImplementationGuide
import org.hl7.fhir.r4.model.ListResource
import org.hl7.fhir.r4.model.MetadataResource
import org.hl7.fhir.r4.model.Resource
Expand Down Expand Up @@ -404,7 +405,7 @@
sharedPreferencesHelper.read(SharedPreferenceKey.APP_ID.name, null)?.let { appId ->
val parsedAppId = appId.substringBefore(TYPE_REFERENCE_DELIMITER).trim()
val patientRelatedResourceTypes = mutableListOf<ResourceType>()
val compositionResource = fetchRemoteComposition(parsedAppId)
val compositionResource = fetchRemoteCompositionByAppId(parsedAppId)
compositionResource?.let { composition ->
composition
.retrieveCompositionSections()
Expand Down Expand Up @@ -451,11 +452,42 @@
}
}

suspend fun fetchRemoteComposition(appId: String?): Composition? {
Timber.i("Fetching configs for app $appId")
val urlPath =
"${ResourceType.Composition.name}?${Composition.SP_IDENTIFIER}=$appId&_count=$DEFAULT_COUNT"
suspend fun fetchRemoteImplementationGuide(
pld marked this conversation as resolved.
Show resolved Hide resolved
appId: String?,
version: String?,
): ImplementationGuide? {
Timber.i("Fetching ImplementationGuide config for app $appId version $version")

Check warning on line 459 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L459

Added line #L459 was not covered by tests

val urlPath = "ImplementationGuide?url=ImplementationGuide/$appId&version=$version"
return fhirResourceDataSource.getResource(urlPath).entryFirstRep.let {

Check warning on line 462 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L461-L462

Added lines #L461 - L462 were not covered by tests
if (!it.hasResource()) {
Timber.w("No response for ImplementationGuide resource on path $urlPath")
return null

Check warning on line 465 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L464-L465

Added lines #L464 - L465 were not covered by tests
}

it.resource as ImplementationGuide

Check warning on line 468 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L468

Added line #L468 was not covered by tests
}
}

suspend fun fetchRemoteCompositionById(
id: String?,
version: String?,
): Composition? {
Timber.i("Fetching Composition config id $id version $version")
val urlPath = "Composition/$id/_history/$version"
return fhirResourceDataSource.getResource(urlPath).entryFirstRep.let {

Check warning on line 478 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L476-L478

Added lines #L476 - L478 were not covered by tests
if (!it.hasResource()) {
Timber.w("No response for composition resource on path $urlPath")
return null

Check warning on line 481 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L480-L481

Added lines #L480 - L481 were not covered by tests
}

it.resource as Composition

Check warning on line 484 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt#L484

Added line #L484 was not covered by tests
}
}

suspend fun fetchRemoteCompositionByAppId(appId: String?): Composition? {
Timber.i("Fetching Composition config for app $appId")
val urlPath = "Composition?identifier=$appId&_count=$DEFAULT_COUNT"
return fhirResourceDataSource.getResource(urlPath).entryFirstRep.let {
if (!it.hasResource()) {
Timber.w("No response for composition resource on path $urlPath")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.hl7.fhir.r4.model.Group
import org.hl7.fhir.r4.model.HumanName
import org.hl7.fhir.r4.model.Immunization
import org.hl7.fhir.r4.model.ImplementationGuide
import org.hl7.fhir.r4.model.Location
import org.hl7.fhir.r4.model.Observation
import org.hl7.fhir.r4.model.Patient
Expand Down Expand Up @@ -382,6 +383,14 @@
}
}

fun ImplementationGuide.retrieveImplementationGuideDefinitionResources():
List<ImplementationGuide.ImplementationGuideDefinitionResourceComponent> {
val resources =
mutableListOf<ImplementationGuide.ImplementationGuideDefinitionResourceComponent>()
this.definition.resource.forEach { resources.add(it) }
return resources

Check warning on line 391 in android/engine/src/main/java/org/smartregister/fhircore/engine/util/extension/ResourceExtension.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/util/extension/ResourceExtension.kt#L388-L391

Added lines #L388 - L391 were not covered by tests
}

hilpitome marked this conversation as resolved.
Show resolved Hide resolved
/**
* Composition sections can be nested. This function retrieves all the nested composition sections
* and returns a flattened list of all [Composition.SectionComponent] for the given [Composition]
Expand Down
1 change: 1 addition & 0 deletions android/engine/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<string name="app_logo">Application logo</string>
<string name="powered_by">Powered By</string>
<string name="app_version">App version %1$d(%2$s)</string>
<string name="ig_version">ImplementationGuide version %s</string>
hilpitome marked this conversation as resolved.
Show resolved Hide resolved
<string name="last_sync">Last sync %1$s</string>
<string name="login_text">LOGIN</string>
<string name="login_call_fail_error_message">Failed to verify credentials from the server. Check your internet connection</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"resourceType": "ImplementationGuide",
"id": "12967310",
"url": "ImplementationGuide/quest",
"version": "1.1.0",
"name": "quest",
"title": "Quest Implementation Guide",
"status": "draft",
"packageId": "org.smartregister.fhircore",
"date": "2024-04-01",
"publisher": "Ona Systems, Inc.",
"fhirVersion": [
{
"code": {
"coding": [
{
"system": "http://hl7.org/fhir/FHIR-version",
"code": "4.3.0",
"display": "4.3.0"
}
],
"text": "FHIR Release 4B."
}
}
],
"useContext": {
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
"code": "program",
"display": "Program"
}
],
"text": "Program"
},
"valueRange": {
"low": {
"value": 1
},
"high": {
"value": 10
}
}
},
"definition": {
"resource": [
{
"reference": {
"reference": "Composition/8294"
}
}
pld marked this conversation as resolved.
Show resolved Hide resolved
]
}
}
1 change: 0 additions & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,3 @@ android.defaults.buildfeatures.buildconfig=true
android.suppressUnsupportedCompileSdk=34
android.jetifier.ignorelist=jackson-core
org.gradle.warning.mode=all
android.suppressUnsupportedCompileSdk=34
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ import org.smartregister.fhircore.quest.ui.login.LoginActivity
import retrofit2.HttpException
import timber.log.Timber

typealias QuestBuildConfig = org.smartregister.fhircore.quest.BuildConfig

@HiltViewModel
class AppSettingViewModel
@Inject
Expand Down Expand Up @@ -93,20 +95,45 @@ constructor(
if (!appId.isNullOrEmpty()) {
when {
hasDebugSuffix() -> loadConfigurations(context)
else -> fetchRemoteConfigurations(appId, context)
else -> fetchRemoteConfigurations(appId, QuestBuildConfig.VERSION_NAME.substringBefore("-"), context)
}
}
}

private fun fetchRemoteConfigurations(appId: String?, context: Context) {
private fun fetchRemoteConfigurations(appId: String?, appVersion: String?, context: Context) {
viewModelScope.launch {
try {
showProgressBar.postValue(true)
Timber.i("Fetching configs for app $appId")
val compositionResource =
withContext(dispatcherProvider.io()) {
configurationRegistry.fetchRemoteComposition(appId)
}

Timber.i("Fetching configs for app $appId version $appVersion")

var compositionResource: Composition? = null
try {
val implementationGuideResource =
configurationRegistry.fetchRemoteImplementationGuide(appId, appVersion)

compositionResource =
if (implementationGuideResource != null) {
configurationRegistry.addOrUpdate(implementationGuideResource)

val compositionReference =
implementationGuideResource.definition.resource[0].reference.reference
hilpitome marked this conversation as resolved.
Show resolved Hide resolved

val compositionIdWithHistory = compositionReference?.substringAfter('/')
val compositionId = compositionIdWithHistory?.substringBefore('/')
val compositionVersion = compositionIdWithHistory?.substringAfterLast('/', "")

withContext(dispatcherProvider.io()) {
configurationRegistry.fetchRemoteCompositionById(compositionId, compositionVersion)
}
pld marked this conversation as resolved.
Show resolved Hide resolved
} else {
withContext(dispatcherProvider.io()) {
configurationRegistry.fetchRemoteCompositionByAppId(appId)
}
}
} catch (e: Exception) {
Timber.e(e)
pld marked this conversation as resolved.
Show resolved Hide resolved
}

if (compositionResource == null) {
showProgressBar.postValue(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
allowP2PSync: Boolean,
lastSyncTime: String?,
showProgressIndicatorFlow: MutableStateFlow<Boolean>,
implementationGuideVersion: String? = null,
) {
val context = LocalContext.current
val (showProgressBar, messageResource) = progressBarState
Expand Down Expand Up @@ -380,6 +381,16 @@
modifier = modifier.padding(top = 8.dp).align(Alignment.CenterHorizontally),
)

if (implementationGuideVersion != null) {
Text(
color = contentColor,
fontSize = 16.sp,

Check warning on line 387 in android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt

View check run for this annotation

Codecov / codecov/patch

android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt#L385-L387

Added lines #L385 - L387 were not covered by tests
text = stringResource(id = R.string.ig_version, implementationGuideVersion),
modifier =
modifier.padding(bottom = 12.dp, top = 2.dp).align(Alignment.CenterHorizontally),

Check warning on line 390 in android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt

View check run for this annotation

Codecov / codecov/patch

android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingScreen.kt#L390

Added line #L390 was not covered by tests
)
}

pld marked this conversation as resolved.
Show resolved Hide resolved
Text(
color = contentColor,
fontSize = 16.sp,
Expand Down Expand Up @@ -496,5 +507,6 @@
allowP2PSync = true,
lastSyncTime = "05:30 PM, Mar 3",
showProgressIndicatorFlow = MutableStateFlow(false),
implementationGuideVersion = "10",
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import kotlinx.coroutines.runBlocking
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.Composition
import org.hl7.fhir.r4.model.Identifier
import org.hl7.fhir.r4.model.ImplementationGuide
import org.hl7.fhir.r4.model.ListResource
import org.hl7.fhir.r4.model.Reference
import org.hl7.fhir.r4.model.StructureMap
Expand Down Expand Up @@ -101,6 +102,21 @@ class ConfigurationRegistryTest : RobolectricTest() {

@Test
fun testFetchNonWorkflowConfigurations() = runBlocking {
val implementationGuide =
ImplementationGuide().apply {
url = "ImplementationGuide/1"
name = "testImplementationGuide"
definition =
ImplementationGuide.ImplementationGuideDefinitionComponent().apply {
resource =
mutableListOf(
ImplementationGuide.ImplementationGuideDefinitionResourceComponent(
Reference().apply { reference = "Composition/_history/12" },
),
)
}
}

val composition =
Composition().apply {
addSection().apply {
Expand All @@ -120,7 +136,10 @@ class ConfigurationRegistryTest : RobolectricTest() {
}

every { secureSharedPreference.retrieveSessionUsername() } returns "demo"
coEvery { configurationRegistry.fetchRemoteImplementationGuide(any()) } returns
implementationGuide
coEvery { configurationRegistry.fetchRemoteComposition(any()) } returns composition
coEvery { configurationRegistry.fhirResourceDataSource.getResource(any()) } returns bundle
coEvery { configurationRegistry.fhirResourceDataSource.post(any(), any()) } returns bundle
every { sharedPreferencesHelper.read(SharedPreferenceKey.APP_ID.name, null) } returns "demo"
coEvery { configurationRegistry.saveSyncSharedPreferences(any()) } just runs
Expand All @@ -131,6 +150,21 @@ class ConfigurationRegistryTest : RobolectricTest() {

@Test
fun testFetchListResourceNonProxy() = runBlocking {
val implementationGuide =
ImplementationGuide().apply {
url = "ImplementationGuide/1"
name = "testImplementationGuide"
definition =
ImplementationGuide.ImplementationGuideDefinitionComponent().apply {
resource =
mutableListOf(
ImplementationGuide.ImplementationGuideDefinitionResourceComponent(
Reference().apply { reference = "Composition" },
),
)
}
}

val composition =
Composition().apply {
addSection().apply {
Expand All @@ -148,8 +182,10 @@ class ConfigurationRegistryTest : RobolectricTest() {

configurationRegistry.setNonProxy(true)
every { secureSharedPreference.retrieveSessionUsername() } returns "demo"
coEvery { configurationRegistry.fetchRemoteComposition(any()) } returns composition

coEvery { configurationRegistry.fetchRemoteImplementationGuide(any()) } returns
implementationGuide
coEvery { configurationRegistry.fetchRemoteCompositionWiByVersion(any(), any()) } returns
composition
coEvery { configurationRegistry.fhirResourceDataSource.getResource(any()) } returns bundle
every { sharedPreferencesHelper.read(SharedPreferenceKey.APP_ID.name, null) } returns "demo"
coEvery { configurationRegistry.saveSyncSharedPreferences(any()) } just runs
Expand All @@ -162,6 +198,21 @@ class ConfigurationRegistryTest : RobolectricTest() {

@Test
fun testFetchListResource() = runBlocking {
val implementationGuide =
ImplementationGuide().apply {
url = "ImplementationGuide/1"
name = "testImplementationGuide"
definition =
ImplementationGuide.ImplementationGuideDefinitionComponent().apply {
resource =
mutableListOf(
ImplementationGuide.ImplementationGuideDefinitionResourceComponent(
Reference().apply { reference = "Composition" },
),
)
}
}

val composition =
Composition().apply {
addSection().apply {
Expand All @@ -184,7 +235,10 @@ class ConfigurationRegistryTest : RobolectricTest() {
}

every { secureSharedPreference.retrieveSessionUsername() } returns "demo"
coEvery { configurationRegistry.fetchRemoteComposition(any()) } returns composition
coEvery { configurationRegistry.fetchRemoteImplementationGuide(any()) } returns
implementationGuide
coEvery { configurationRegistry.fetchRemoteCompositionWiByVersion(any(), any()) } returns
composition
coEvery {
fhirResourceService.getResourceWithGatewayModeHeader(
ConfigurationRegistry.FHIR_GATEWAY_MODE_HEADER_VALUE,
Expand Down
Loading
Loading