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

fixes edit profile - questionItems disable via readOnlyLinkIds #3218

Merged
merged 3 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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 @@ -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 @@ -40,13 +40,13 @@ abstract class RobolectricTest {
val data = arrayOfNulls<Any>(1)
val latch = CountDownLatch(1)
val observer: Observer<T> =
object : Observer<T> {
override fun onChanged(o: T?) {
data[0] = o
latch.countDown()
liveData.removeObserver(this)
}
}
Observer<T>
// override fun onChanged(o: T?) {
// data[0] = o
// latch.countDown()
// liveData.removeObserver(this)
// }
{ TODO("Not yet implemented") }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of commenting these lines, make the function parameter o NON-NULLABLE by removing the question mark.

override fun onChanged(o: T) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

liveData.observeForever(observer)
latch.await(3, TimeUnit.SECONDS)
@Suppress("UNCHECKED_CAST") return data[0] as T?
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()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ellykits , here its the main change I found to fix the underline issue,
the required/expected behavior is handle with line 141 below.

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