Skip to content

Commit

Permalink
fixes edit profile - questionItems disable via readOnlyLinkIds (#3218)
Browse files Browse the repository at this point in the history
* fixes edit profile - questionItems disable via readOnlyLinkIds
Revert fhircore PR#3069

* comment as per reviewer feedback

---------

Co-authored-by: Benjamin Mwalimu <dubdabasoduba@gmail.com>
  • Loading branch information
AbdulWahabMemon and dubdabasoduba authored May 6, 2024
1 parent a571668 commit 4d2d504
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,15 @@ fun List<Questionnaire.QuestionnaireItemComponent>.generateMissingItems(
}
}
}

/**
* Set all questions that are not of type [Questionnaire.QuestionnaireItemType.GROUP] to readOnly if
* [readOnly] is true. This also generates the correct FHIRPath population expression for each
* question when mapped to the corresponding [QuestionnaireResponse]
*/
fun List<Questionnaire.QuestionnaireItemComponent>.prepareQuestionsForReadingOrEditing(
path: String,
readOnly: Boolean,
readOnly: Boolean = false,
readOnlyLinkIds: List<String>? = emptyList()
) {
forEach { item ->
Expand All @@ -214,6 +215,31 @@ fun List<Questionnaire.QuestionnaireItemComponent>.prepareQuestionsForReadingOrE
}
}

/**
* Set all questions that are not of type [Questionnaire.QuestionnaireItemType.GROUP] to readOnly if
* [readOnlyLinkIds] item are there while editing the form. This also generates the correct FHIRPath
* population expression for each question when mapped to the corresponding [QuestionnaireResponse]
*/
fun List<Questionnaire.QuestionnaireItemComponent>.prepareQuestionsForEditing(
path: String,
readOnlyLinkIds: List<String>? = emptyList()
) {
forEach { item ->
if (item.type != Questionnaire.QuestionnaireItemType.GROUP) {
item.readOnly = readOnlyLinkIds?.contains(item.linkId) == true
item.item.prepareQuestionsForEditing(
"$path.where(linkId = '${item.linkId}').answer.item",
readOnlyLinkIds
)
} else {
item.item.prepareQuestionsForEditing(
"$path.where(linkId = '${item.linkId}').item",
readOnlyLinkIds
)
}
}
}

/** Delete resources in [QuestionnaireResponse.contained] from the database */
suspend fun QuestionnaireResponse.deleteRelatedResources(defaultRepository: DefaultRepository) {
contained.forEach { defaultRepository.delete(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.smartregister.fhircore.engine.configuration

import dagger.hilt.android.testing.HiltAndroidTest
import org.hl7.fhir.r4.model.ResourceType
import org.junit.Assert
import org.junit.Test
import org.smartregister.fhircore.engine.configuration.event.EventWorkflow
Expand Down Expand Up @@ -62,7 +63,7 @@ class QuestionnaireConfigTest : RobolectricTest() {
groupResource =
GroupResourceConfig(
groupIdentifier = "@{groupIdentifier}",
memberResourceType = "Condition",
memberResourceType = ResourceType.Condition,
removeMember = true,
removeGroup = true,
deactivateMembers = false
Expand Down Expand Up @@ -131,7 +132,7 @@ class QuestionnaireConfigTest : RobolectricTest() {
@Test
fun testDefaultGroupResourceConfig() {
val groupIdentifier = "groupIdentifier"
val memberResourceType = "Condition"
val memberResourceType = ResourceType.Condition
val groupResourceConfig = GroupResourceConfig(groupIdentifier, memberResourceType)
groupResourceConfig.apply {
Assert.assertEquals(groupIdentifier, this.groupIdentifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ class DefaultRepositoryTest : RobolectricTest() {
defaultRepositorySpy.removeGroupMember(
memberId,
null,
patientMemberRep.resourceType.name,
patientMemberRep.resourceType,
emptyMap()
)
Assert.assertFalse(patientMemberRep.active)
Expand All @@ -627,7 +627,7 @@ class DefaultRepositoryTest : RobolectricTest() {
defaultRepositorySpy.removeGroupMember(
memberId,
null,
patientMemberRep.resourceType.name,
patientMemberRep.resourceType,
emptyMap()
)
Assert.assertTrue(patientMemberRep.active)
Expand Down Expand Up @@ -718,7 +718,7 @@ class DefaultRepositoryTest : RobolectricTest() {
defaultRepository.removeGroupMember(
memberId = memberId,
groupId = groupId,
groupMemberResourceType = groupMemberResourceType,
memberResourceType = ResourceType.Patient,
emptyMap()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import dagger.hilt.android.testing.HiltTestApplication
import io.mockk.clearAllMocks
import java.io.File
import java.io.FileReader
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import org.junit.AfterClass
import org.junit.BeforeClass
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import org.smartregister.fhircore.engine.app.fakes.FakeKeyStore
import java.io.File
import java.io.FileReader
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

@RunWith(FhircoreTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class)
Expand All @@ -41,7 +41,7 @@ abstract class RobolectricTest {
val latch = CountDownLatch(1)
val observer: Observer<T> =
object : Observer<T> {
override fun onChanged(o: T?) {
override fun onChanged(o: T) {
data[0] = o
latch.countDown()
liveData.removeObserver(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import io.mockk.coVerify
import io.mockk.mockk
import java.math.BigDecimal
import java.util.Date
import junit.framework.Assert.assertEquals
import kotlinx.coroutines.runBlocking
import org.hl7.fhir.r4.model.BooleanType
import org.hl7.fhir.r4.model.CodeableConcept
Expand Down Expand Up @@ -746,4 +745,17 @@ class ResourceExtensionTest : RobolectricTest() {
Assert.assertTrue(questionnaire.item[1].readOnly)
Assert.assertTrue(questionnaire.item[2].readOnly)
}

@Test
fun `prepareQuestionsForEditing should set readOnly correctly when readOnlyLinkIds passed`() {
val questionnaire = Questionnaire()
questionnaire.item.add(Questionnaire.QuestionnaireItemComponent().apply { linkId = "1" })
questionnaire.item.add(Questionnaire.QuestionnaireItemComponent().apply { linkId = "2" })
questionnaire.item.add(Questionnaire.QuestionnaireItemComponent().apply { linkId = "3" })
questionnaire.item.prepareQuestionsForEditing("", readOnlyLinkIds = listOf("1", "3"))

Assert.assertTrue(questionnaire.item[0].readOnly)
Assert.assertFalse(questionnaire.item[1].readOnly)
Assert.assertTrue(questionnaire.item[2].readOnly)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ open class QuestionnaireActivity : BaseMultiLanguageActivity(), View.OnClickList
val questionnaire =
questionnaireViewModel.loadQuestionnaire(
questionnaireConfig = questionnaireConfig,
prePopulationParams = prePopulationParams
prePopulationParams = prePopulationParams,
readOnlyLinkIds = questionnaireConfig.readOnlyLinkIds
)
if (questionnaire == null) {
showToast(getString(R.string.questionnaire_not_found))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import org.smartregister.fhircore.engine.util.extension.findSubject
import org.smartregister.fhircore.engine.util.extension.isExtractionCandidate
import org.smartregister.fhircore.engine.util.extension.isIn
import org.smartregister.fhircore.engine.util.extension.prePopulateInitialValues
import org.smartregister.fhircore.engine.util.extension.prepareQuestionsForEditing
import org.smartregister.fhircore.engine.util.extension.prepareQuestionsForReadingOrEditing
import org.smartregister.fhircore.engine.util.extension.referenceValue
import org.smartregister.fhircore.engine.util.extension.resourceClassType
Expand Down Expand Up @@ -130,13 +131,16 @@ constructor(
readOnlyLinkIds: List<String>? = emptyList()
): Questionnaire? =
defaultRepository.loadResource<Questionnaire>(questionnaireConfig.id)?.apply {
if (questionnaireConfig.type.isReadOnly() || questionnaireConfig.type.isEditMode()) {
if (questionnaireConfig.type.isReadOnly()) {
item.prepareQuestionsForReadingOrEditing(
QUESTIONNAIRE_RESPONSE_ITEM,
questionnaireConfig.type.isReadOnly() || questionnaireConfig.type.isEditMode(),
questionnaireConfig.type.isReadOnly(),
readOnlyLinkIds
)
}
if (questionnaireConfig.type.isEditMode()) {
item.prepareQuestionsForEditing(QUESTIONNAIRE_RESPONSE_ITEM, readOnlyLinkIds)
}
// prepopulate questionnaireItems with initial values
prePopulationParams?.takeIf { it.isNotEmpty() }?.let { nonEmptyParams ->
editQuestionnaireResourceParams =
Expand Down Expand Up @@ -273,12 +277,14 @@ constructor(
else if (bundleEntry.resource.resourceType.isIn(ResourceType.List)) {
// No need to update List resource subject to the questionnaire subject
// only need to change location reference as in entry.item-reference
val lastLocationRes =
bundle.entry
.first { item -> item.resource.resourceType.isIn(ResourceType.Group) }
.resource
(bundleEntry.resource as ListResource).entry[0].item.reference =
(lastLocationRes as Group).referenceValue()
if (!bundle.entry.first().hasResource()) {
val lastLocationRes =
bundle.entry
.first { item -> item.resource.resourceType.isIn(ResourceType.Group) }
.resource
(bundleEntry.resource as ListResource).entry[0].item.reference =
(lastLocationRes as Group).referenceValue()
}
} else {
bundleEntry.resource.setPropertySafely("subject", questionnaireResponse.subject)
bundleEntry.resource.setPropertySafely("patient", questionnaireResponse.subject)
Expand Down

0 comments on commit 4d2d504

Please sign in to comment.