Skip to content

Commit

Permalink
fix: [ANDROAPP-6667] Add field to warning list for warning on complet…
Browse files Browse the repository at this point in the history
…e program rule (#3917)

* fix: [ANDROAPP-6667] Add field to warning list for warning on complete rule

* fix: [ANDROAPP-6667] display warning/error on complete

Signed-off-by: Manu Muñoz <[email protected]>

* fix: [ANDROAPP-6667] add tests

Signed-off-by: Manu Muñoz <[email protected]>

* fix: [ANDROAPP-6667] fix test

Signed-off-by: Manu Muñoz <[email protected]>

* fix test

Signed-off-by: Manu Muñoz <[email protected]>

---------

Signed-off-by: Manu Muñoz <[email protected]>
Co-authored-by: Manu Muñoz <[email protected]>
  • Loading branch information
xavimolloy and mmmateos authored Dec 18, 2024
1 parent 115ce42 commit fe8afe2
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ class ProgramEventTest : BaseTest() {
}

eventRobot(composeTestRule) {
openEventDetailsSection()
checkEventDetails(eventDate, eventOrgUnit)
}
}
Expand Down
52 changes: 12 additions & 40 deletions form/src/main/java/org/dhis2/form/data/FormRepositoryImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class FormRepositoryImpl(

return when {
(itemsWithErrors.isEmpty() && itemsWithWarning.isEmpty() && mandatoryItemsWithoutValue.isEmpty()) -> {
getSuccessfulResult(eventStatus)
getSuccessfulResult()
}

(itemsWithErrors.isNotEmpty()) -> {
Expand Down Expand Up @@ -285,7 +285,7 @@ class FormRepositoryImpl(
EventStatus.COMPLETED -> {
FieldsWithWarningResult(
fieldUidWarningList = itemsWithWarning,
canComplete = false,
canComplete = ruleEffectsResult?.canComplete ?: false,
onCompleteMessage = ruleEffectsResult?.messageOnComplete,
eventResultDetails = EventResultDetails(
formValueStore.eventState(),
Expand Down Expand Up @@ -427,44 +427,16 @@ class FormRepositoryImpl(
}
}

private fun getSuccessfulResult(eventStatus: EventStatus?): SuccessfulResult {
return when (eventStatus) {
EventStatus.ACTIVE -> {
SuccessfulResult(
canComplete = ruleEffectsResult?.canComplete ?: true,
onCompleteMessage = ruleEffectsResult?.messageOnComplete,
eventResultDetails = EventResultDetails(
formValueStore.eventState(),
dataEntryRepository.eventMode(),
dataEntryRepository.validationStrategy(),
),
)
}

EventStatus.COMPLETED -> {
SuccessfulResult(
canComplete = false,
onCompleteMessage = ruleEffectsResult?.messageOnComplete,
eventResultDetails = EventResultDetails(
formValueStore.eventState(),
dataEntryRepository.eventMode(),
dataEntryRepository.validationStrategy(),
),
)
}

else -> {
SuccessfulResult(
canComplete = ruleEffectsResult?.canComplete ?: false,
onCompleteMessage = ruleEffectsResult?.messageOnComplete,
eventResultDetails = EventResultDetails(
formValueStore.eventState(),
dataEntryRepository.eventMode(),
validationStrategy = dataEntryRepository.validationStrategy(),
),
)
}
}
private fun getSuccessfulResult(): SuccessfulResult {
return SuccessfulResult(
canComplete = ruleEffectsResult?.canComplete ?: true,
onCompleteMessage = ruleEffectsResult?.messageOnComplete,
eventResultDetails = EventResultDetails(
formValueStore.eventState(),
dataEntryRepository.eventMode(),
dataEntryRepository.validationStrategy(),
),
)
}

override fun completedFieldsPercentage(value: List<FieldUiModel>): Float {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@ class RulesUtilsProviderImpl(
val message = warningOnCompletion.content() + " " + data
if (model != null) {
fieldViewModels[fieldUid] = model.setWarning(message)
fieldsWithWarnings.add(
FieldWithError(fieldUid, message),
)
}

messageOnComplete = message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ class FormResultDialogProvider(
eventState: EventStatus?,
result: DataIntegrityCheckResult,
): Pair<BottomSheetDialogUiModel, List<FieldWithIssue>> {
val onCompleteMessages = getOnCompleteMessage(
canComplete,
onCompleteMessage,
)
val dialogType = getDialogType(
errorFields,
emptyMandatoryFields,
warningFields,
!canComplete && onCompleteMessage != null,
onCompleteMessages,
)
val showSkipButton = when {
dialogType == DialogType.WARNING || dialogType == DialogType.SUCCESSFUL -> true
Expand Down Expand Up @@ -74,12 +78,14 @@ class FormResultDialogProvider(
result.fieldUidErrorList,
result.mandatoryFields.keys.toList(),
result.warningFields,
onCompleteMessages,
)
Pair(model, fieldsWithIssues)
}
is FieldsWithWarningResult -> {
val fieldsWithIssues = getFieldsWithIssues(
warningFields = result.fieldUidWarningList,
onCompleteFields = onCompleteMessages,
)
return Pair(model, fieldsWithIssues)
}
Expand All @@ -101,7 +107,7 @@ class FormResultDialogProvider(
Pair(notSavedModel, emptyList())
}
is SuccessfulResult -> {
Pair(model, emptyList())
Pair(model, onCompleteMessages)
}
}
}
Expand Down Expand Up @@ -166,44 +172,54 @@ class FormResultDialogProvider(
errorFields: List<FieldWithIssue> = emptyList(),
mandatoryFields: List<String> = emptyList(),
warningFields: List<FieldWithIssue> = emptyList(),
onCompleteFields: List<FieldWithIssue> = emptyList(),
): List<FieldWithIssue> {
return errorFields.plus(
mandatoryFields.map {
FieldWithIssue(
"uid",
it,
IssueType.MANDATORY,
provider.provideMandatoryField(),
)
},
).plus(warningFields)
return onCompleteFields
.plus(errorFields)
.plus(
mandatoryFields.map {
FieldWithIssue(
"uid",
it,
IssueType.MANDATORY,
provider.provideMandatoryField(),
)
},
).plus(warningFields)
}

private fun getOnCompleteMessage(
canComplete: Boolean,
onCompleteMessage: String?,
): List<FieldWithIssue> {
val issueOnComplete = onCompleteMessage?.let {
FieldWithIssue(
fieldUid = "",
fieldName = it,
issueType = when (canComplete) {
false -> IssueType.ERROR_ON_COMPLETE
else -> IssueType.WARNING_ON_COMPLETE
},
message = "",
)
}
return issueOnComplete?.let { listOf(it) } ?: emptyList()
}

private fun getDialogType(
errorFields: List<FieldWithIssue>,
mandatoryFields: Map<String, String>,
warningFields: List<FieldWithIssue>,
errorOnComplete: Boolean,
onCompleteFields: List<FieldWithIssue>,
) = when {
errorOnComplete -> {
onCompleteFields.any { it.issueType == IssueType.ERROR_ON_COMPLETE } ->
DialogType.COMPLETE_ERROR
}

errorFields.isNotEmpty() -> {
DialogType.ERROR
}

mandatoryFields.isNotEmpty() -> {
DialogType.MANDATORY
}

warningFields.isNotEmpty() -> {
errorFields.isNotEmpty() -> DialogType.ERROR
mandatoryFields.isNotEmpty() -> DialogType.MANDATORY
warningFields.isNotEmpty() ||
onCompleteFields.any { it.issueType == IssueType.WARNING_ON_COMPLETE } ->
DialogType.WARNING
}

else -> {
DialogType.SUCCESSFUL
}
else -> DialogType.SUCCESSFUL
}
enum class DialogType { ERROR, MANDATORY, WARNING, SUCCESSFUL, COMPLETE_ERROR }
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import org.mockito.kotlin.atLeast
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doReturnConsecutively
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

Expand Down Expand Up @@ -290,16 +289,16 @@ class FormRepositoryImplTest {
fun `Should allow to complete only uncompleted events`() {
whenever(
dataEntryRepository.list(),
) doReturn Flowable.just(provideMandatoryItemList().filter { !it.mandatory })
) doReturn Flowable.just(provideMandatoryItemList())
whenever(dataEntryRepository.isEvent()) doReturn true
whenever(formValueStore.eventState()) doReturn EventStatus.ACTIVE
repository.fetchFormItems()
assertTrue(repository.runDataIntegrityCheck(false) is SuccessfulResult)
assertTrue(repository.runDataIntegrityCheck(false) is MissingMandatoryResult)
assertTrue(repository.runDataIntegrityCheck(false).canComplete)
whenever(formValueStore.eventState()) doReturn EventStatus.COMPLETED
repository.fetchFormItems()

assertTrue(repository.runDataIntegrityCheck(false) is SuccessfulResult)
assertTrue(repository.runDataIntegrityCheck(false) is MissingMandatoryResult)
assertFalse(repository.runDataIntegrityCheck(false).canComplete)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ class RulesUtilsProviderImplTest {

assertEquals(testFieldViewModels[testingUid]!!.warning, "content data")
assertTrue(result.messageOnComplete == "content data")
assertTrue(result.fieldsWithWarnings.isNotEmpty())
assertTrue(result.canComplete)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.dhis2.form.data.MissingMandatoryResult
import org.dhis2.form.data.SuccessfulResult
import org.dhis2.form.model.EventMode
import org.dhis2.ui.dialogs.bottomsheet.DialogButtonStyle
import org.dhis2.ui.dialogs.bottomsheet.IssueType
import org.hisp.dhis.android.core.common.ValidationStrategy
import org.hisp.dhis.android.core.event.EventStatus
import org.junit.Assert.assertTrue
Expand Down Expand Up @@ -98,6 +99,54 @@ class FormResultDialogProviderTest {
assertTrue(noErrorsInFormModel.first.mainButton == DialogButtonStyle.CompleteButton)
}

@Test
fun `Should configure to show warning on complete message`() {
val completedEventWithNoErrors = SuccessfulResult(
canComplete = true,
onCompleteMessage = "Warning on complete",
eventResultDetails = EventResultDetails(
eventStatus = EventStatus.ACTIVE,
eventMode = EventMode.CHECK,
validationStrategy = ValidationStrategy.ON_COMPLETE,
),
)
val noErrorsInFormModel = formResultDialogProvider.invoke(
canComplete = completedEventWithNoErrors.canComplete,
onCompleteMessage = completedEventWithNoErrors.onCompleteMessage,
errorFields = emptyList(),
emptyMandatoryFields = emptyMap(),
warningFields = emptyList(),
eventMode = completedEventWithNoErrors.eventResultDetails.eventMode ?: EventMode.NEW,
eventState = completedEventWithNoErrors.eventResultDetails.eventStatus ?: EventStatus.ACTIVE,
result = completedEventWithNoErrors,
)
assertTrue(noErrorsInFormModel.second.first().issueType == IssueType.WARNING_ON_COMPLETE)
}

@Test
fun `Should configure to show error on complete message`() {
val completedEventWithNoErrors = SuccessfulResult(
canComplete = false,
onCompleteMessage = "error on complete",
eventResultDetails = EventResultDetails(
eventStatus = EventStatus.ACTIVE,
eventMode = EventMode.NEW,
validationStrategy = ValidationStrategy.ON_COMPLETE,
),
)
val noErrorsInFormModel = formResultDialogProvider.invoke(
canComplete = completedEventWithNoErrors.canComplete,
onCompleteMessage = completedEventWithNoErrors.onCompleteMessage,
errorFields = emptyList(),
emptyMandatoryFields = emptyMap(),
warningFields = emptyList(),
eventMode = completedEventWithNoErrors.eventResultDetails.eventMode ?: EventMode.NEW,
eventState = completedEventWithNoErrors.eventResultDetails.eventStatus ?: EventStatus.ACTIVE,
result = completedEventWithNoErrors,
)
assertTrue(noErrorsInFormModel.second.first().issueType == IssueType.ERROR_ON_COMPLETE)
}

@Test
fun `Should follow validation strategy when trying to save the form with errors`() {
val completedEventWithNoErrors = SuccessfulResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,13 @@ fun IssueItem(fieldWithIssue: FieldWithIssue, onClick: () -> Unit) {
color = textPrimary,
fontSize = 14.sp,
)
Text(
text = fieldWithIssue.message,
color = textSecondary,
fontSize = 14.sp,
)
if (fieldWithIssue.message.isNotEmpty()) {
Text(
text = fieldWithIssue.message,
color = textSecondary,
fontSize = 14.sp,
)
}
}
}
}
Expand Down Expand Up @@ -308,7 +310,7 @@ fun DialogPreview3() {
fun DialogPreview4() {
val fieldsWithIssues = listOf(
FieldWithIssue("Uid", "Age", IssueType.ERROR, ERROR_MESSAGE),
FieldWithIssue("Uid", DATE_BIRTH, IssueType.ERROR, ERROR_MESSAGE),
FieldWithIssue("Uid", DATE_BIRTH, IssueType.ERROR, ""),
FieldWithIssue("Uid", DATE_BIRTH, IssueType.ERROR, ERROR_MESSAGE),
FieldWithIssue("Uid", DATE_BIRTH, IssueType.ERROR, ERROR_MESSAGE),
FieldWithIssue("Uid", DATE_BIRTH, IssueType.ERROR, ERROR_MESSAGE),
Expand Down

0 comments on commit fe8afe2

Please sign in to comment.