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

ANDROAPP-6802-DatasetInstanceScreen-Saving-and-complete-workflow #3991

Open
wants to merge 26 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a5a6083
test: [ANDROAPP-6802] Create CheckValidationRules use case
andresmr Feb 10, 2025
05ed275
test: [ANDROAPP-6802] Create CheckCompletionStatus Use Case
andresmr Feb 11, 2025
3675186
test: [ANDROAPP-6802] Create flow when none validation rules
andresmr Feb 11, 2025
78f67be
test: [ANDROAPP-6802] Create CheckMandatoryFieldsStatus use case
andresmr Feb 13, 2025
22bde89
test: [ANDROAPP-6802] check Mandatory fields by field combination
andresmr Feb 13, 2025
f23167a
test: [ANDROAPP-6802] add close callback
andresmr Feb 13, 2025
3b04294
test: [ANDROAPP-6802] move resourceManager to ui
andresmr Feb 13, 2025
6f7c122
test: [ANDROAPP-6802] CompleteDataSet use case
andresmr Feb 14, 2025
3aa8071
test: [ANDROAPP-6802] Create RunValidationRules use case
andresmr Feb 18, 2025
c4bd7e4
test: [ANDROAPP-6802] Adding completion translations
andresmr Feb 18, 2025
1bd3dca
test: [ANDROAPP-6802] Add transifex config
andresmr Feb 18, 2025
a6eb802
test: [ANDROAPP-6802] Add translations
andresmr Feb 19, 2025
a037c0b
test: [ANDROAPP-6802] remove mockito-kotlin update
andresmr Feb 19, 2025
1a12eb4
test: [ANDROAPP-6802] Implement optional validation rules
andresmr Feb 19, 2025
1e583fd
test: [ANDROAPP-6802] Add CompleteDataSetTest
andresmr Feb 20, 2025
955ad98
test: [ANDROAPP-6802] Add CheckCompletionStatusTest
andresmr Feb 20, 2025
a6c9da0
test: [ANDROAPP-6802] Add tests to DataSetTableViewModel
andresmr Feb 20, 2025
73c45d6
test: [ANDROAPP-6802] ValidationBar errors
andresmr Feb 21, 2025
e493cf8
test: [ANDROAPP-6802] ValidationBar violations
andresmr Feb 24, 2025
16a3bf8
test: [ANDROAPP-6802] ValidationBar violations horizontal pager
andresmr Feb 24, 2025
93e9455
test: [ANDROAPP-6802] UpdateSnackBar
andresmr Feb 25, 2025
f0b0fef
test: [ANDROAPP-6802] Implement SnackbarController
andresmr Feb 26, 2025
4b65e11
test: [ANDROAPP-6802] Moving resource manager
andresmr Feb 26, 2025
502c281
test: [ANDROAPP-6802] clean up ValidationRulesErrorDialog
andresmr Feb 27, 2025
a39f32d
test: [ANDROAPP-6802] Add translations to data to review
andresmr Feb 27, 2025
94203a4
test: [ANDROAPP-6802] Remove composables from DataSetModalDialogUIState
andresmr Feb 27, 2025
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
7 changes: 7 additions & 0 deletions .tx/config
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,10 @@ source_file = tracker/src/main/res/values/strings.xml
source_lang = en
type = ANDROID
minimum_perc = 0

[o:hisp-uio:p:dhis2-android-capture-app:r:aggregates-strings-xml]
file_filter = aggregates/src/commonMain/composeResources/values-<lang>/strings.xml
source_file = aggregates/src/commonMain/composeResources/values/strings.xml
source_lang = en
type = ANDROID
minimum_perc = 0
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,25 @@ import org.dhis2.mobile.aggregates.model.DataSetDetails
import org.dhis2.mobile.aggregates.model.DataSetInstanceConfiguration
import org.dhis2.mobile.aggregates.model.DataSetInstanceSectionConfiguration
import org.dhis2.mobile.aggregates.model.DataSetRenderingConfig
import org.dhis2.mobile.aggregates.model.DataToReview
import org.dhis2.mobile.aggregates.model.MandatoryCellElements
import org.dhis2.mobile.aggregates.model.TableGroup
import org.dhis2.mobile.aggregates.model.ValidationResultStatus
import org.dhis2.mobile.aggregates.model.ValidationRulesResult
import org.dhis2.mobile.aggregates.model.Violation
import org.dhis2.mobile.aggregates.ui.constants.NO_SECTION_UID
import org.hisp.dhis.android.core.D2
import org.hisp.dhis.android.core.arch.helpers.GeometryHelper
import org.hisp.dhis.android.core.arch.helpers.UidsHelper
import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope
import org.hisp.dhis.android.core.common.Geometry
import org.hisp.dhis.android.core.common.State
import org.hisp.dhis.android.core.common.ValueType
import org.hisp.dhis.android.core.dataelement.DataElementOperand
import org.hisp.dhis.android.core.dataset.DataSetEditableStatus
import org.hisp.dhis.android.core.dataset.Section
import org.hisp.dhis.android.core.maintenance.D2Error
import org.hisp.dhis.android.core.validation.engine.ValidationResultViolation

internal class DataSetInstanceRepositoryImpl(
private val d2: D2,
Expand Down Expand Up @@ -70,6 +78,35 @@ internal class DataSetInstanceRepositoryImpl(
.byDataSetUid().eq(dataSetUid)
.blockingGet().map(Section::toDataSetSection)

override suspend fun isComplete(
dataSetUid: String,
periodId: String,
orgUnitUid: String,
attrOptionComboUid: String,
): Boolean {
return d2.dataSetModule().dataSetCompleteRegistrations()
.byDataSetUid().eq(dataSetUid)
.byPeriod().eq(periodId)
.byOrganisationUnitUid().eq(orgUnitUid)
.byAttributeOptionComboUid().eq(attrOptionComboUid)
.byDeleted().isFalse
.isEmpty()
.map { isEmpty -> !isEmpty }.blockingGet()
}

override suspend fun areValidationRulesMandatory(dataSetUid: String): Boolean {
return d2.dataSetModule()
.dataSets().uid(dataSetUid)
.blockingGet()?.validCompleteOnly() ?: false
}

override suspend fun checkIfHasValidationRules(dataSetUid: String): Boolean {
return !d2.validationModule().validationRules()
.byDataSetUids(listOf(dataSetUid))
.bySkipFormValidation().isFalse
.blockingIsEmpty()
}

override suspend fun getRenderingConfig(
dataSetUid: String,
) = d2.dataSetModule().dataSets()
Expand Down Expand Up @@ -423,4 +460,202 @@ internal class DataSetInstanceRepositoryImpl(
).toString()
}.toSortedMap(compareBy { it })
.takeIf { it.isNotEmpty() }

override suspend fun checkIfHasMissingMandatoryFields(
dataSetUid: String,
periodId: String,
orgUnitUid: String,
attributeOptionComboUid: String,
): Boolean {
return !d2.dataSetModule().dataSets().withCompulsoryDataElementOperands().uid(dataSetUid)
.get()
.map {
it.compulsoryDataElementOperands()?.filter { dataElementOperand ->
dataElementOperand.dataElement()?.let { dataElement ->
dataElementOperand.categoryOptionCombo()?.let { categoryOptionCombo ->
!d2.dataValueModule().dataValues()
.value(
periodId,
orgUnitUid,
dataElement.uid(),
categoryOptionCombo.uid(),
attributeOptionComboUid,
).blockingExists()
}
} ?: false
}
}.blockingGet().isNullOrEmpty()
}

override suspend fun checkIfHasMissingMandatoryFieldsCombination(
dataSetUid: String,
periodId: String,
orgUnitUid: String,
attributeOptionComboUid: String,
): Boolean {
return d2.dataSetModule().dataSets().withDataSetElements().uid(dataSetUid).blockingGet()
?.let { dataSet ->
if (dataSet.fieldCombinationRequired() == true) {
dataSet.dataSetElements()
?.filter { dataSetElement ->
val catComboUid = dataSetElement.categoryCombo()?.uid()
?: d2.dataElementModule().dataElements()
.uid(dataSetElement.dataElement().uid())
.blockingGet()?.categoryComboUid()
val categoryOptionCombos =
d2.categoryModule().categoryOptionCombos().byCategoryComboUid()
.eq(catComboUid).blockingGet()
val dataValueRepository = d2.dataValueModule().dataValues()
.byPeriod().eq(periodId)
.byOrganisationUnitUid().eq(orgUnitUid)
.byAttributeOptionComboUid().eq(attributeOptionComboUid)
.byDeleted().isFalse
.byDataElementUid().eq(dataSetElement.dataElement().uid())
.byCategoryOptionComboUid()
.`in`(UidsHelper.getUidsList(categoryOptionCombos))
dataValueRepository.blockingGet().isNotEmpty() &&
dataValueRepository
.blockingCount() != categoryOptionCombos.size
}?.map { dataSetElement ->
dataSetElement.dataElement().uid()
}.isNullOrEmpty().not()
} else {
false
}
} ?: false
}

override suspend fun completeDataset(
dataSetUid: String,
periodId: String,
orgUnitUid: String,
attributeOptionComboUid: String,
): Result<Unit> {
return try {
d2.dataSetModule().dataSetCompleteRegistrations()
.value(periodId, orgUnitUid, dataSetUid, attributeOptionComboUid)
.blockingSet()
Result.success(Unit)
} catch (error: D2Error) {
Result.failure(error)
}
}

override suspend fun runValidationRules(
dataSetUid: String,
periodId: String,
orgUnitUid: String,
attrOptionComboUid: String,
): ValidationRulesResult {
val result = d2.validationModule()
.validationEngine().validate(
dataSetUid,
periodId,
orgUnitUid,
attrOptionComboUid,
).blockingGet()

return ValidationRulesResult(
ValidationResultStatus.valueOf(result.status().name),
mapViolations(
violations = result.violations(),
periodId = periodId,
orgUnitUid = orgUnitUid,
attrOptionComboUid = attrOptionComboUid,
),
)
}

private fun mapViolations(
violations: List<ValidationResultViolation>,
periodId: String,
orgUnitUid: String,
attrOptionComboUid: String,
): List<Violation> {
return violations.map {
Violation(
it.validationRule().description(),
it.validationRule().instruction(),
mapDataElements(
dataElementUids = it.dataElementUids(),
periodId = periodId,
orgUnitUid = orgUnitUid,
attrOptionComboUid = attrOptionComboUid,
),
)
}
}

private fun mapDataElements(
dataElementUids: MutableSet<DataElementOperand>,
periodId: String,
orgUnitUid: String,
attrOptionComboUid: String,
): List<DataToReview> {
val dataToReview = arrayListOf<DataToReview>()
dataElementUids.mapNotNull { deOperand ->
d2.dataElementModule().dataElements()
.uid(deOperand.dataElement()?.uid())
.blockingGet()?.let {
Pair(deOperand, it)
}
}.forEach { (deOperand, de) ->
val catOptCombos =
if (deOperand.categoryOptionCombo() != null) {
d2.categoryModule().categoryOptionCombos()
.byUid().like(deOperand.categoryOptionCombo()?.uid())
.blockingGet()
} else {
d2.categoryModule().categoryOptionCombos()
.byCategoryComboUid().like(de.categoryComboUid())
.blockingGet()
}
catOptCombos.forEach { catOptCombo ->
val value = if (d2.dataValueModule().dataValues()
.value(
periodId,
orgUnitUid,
de.uid(),
catOptCombo.uid(),
attrOptionComboUid,
)
.blockingExists() &&
d2.dataValueModule().dataValues()
.value(
periodId,
orgUnitUid,
de.uid(),
catOptCombo.uid(),
attrOptionComboUid,
)
.blockingGet()?.deleted() != true
) {
d2.dataValueModule().dataValues()
.value(
periodId,
orgUnitUid,
de.uid(),
catOptCombo.uid(),
attrOptionComboUid,
)
.blockingGet()?.value() ?: "-"
} else {
"-"
}
val isFromDefaultCatCombo = d2.categoryModule().categoryCombos()
.uid(catOptCombo.categoryCombo()?.uid()).blockingGet()?.isDefault == true
dataToReview.add(
DataToReview(
de.uid(),
de.displayFormName(),
catOptCombo.uid(),
catOptCombo.displayName(),
value,
isFromDefaultCatCombo,
),
)
}
}
return dataToReview
}
}
15 changes: 15 additions & 0 deletions aggregates/src/commonMain/composeResources/values-ar/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="validation_success_title">كل شيء يبدو جيدا!</string>
<string name="mark_dataset_complete">هل تريد أيضاً تعيين حزمة البيانات كمكتملة؟</string>
<string name="complete">مكتمل</string>
<string name="saved">تم الحفظ!</string>
<string name="field_mandatory">هناك حقول إلزامية مفقودة. من فضلك قم بملؤها لإكمال حزمة البيانات.</string>
<string name="field_required">إذا قمت بتعيين قيمة ، فإن الصف بأكمله يحتاج إلى كل القيم لإكمال مجموعة البيانات.</string>
<string name="ok">موافق</string>
<string name="dataset_saved_completed">محفوظ ومكتمل</string>
<string name="run_validation_rules">هل تريد التحقق من جودة البيانات؟</string>
<string name="error">خطأ</string>
<string name="complete_anyway">إكمال على أية حال</string>

</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="ok">تةواو</string>


</resources>
16 changes: 16 additions & 0 deletions aggregates/src/commonMain/composeResources/values-cs/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="validation_success_title">Všechno vypadá dobře!</string>
<string name="mark_dataset_complete">Chcete také vyplnit soubor dat?</string>
<string name="complete">Dokončit</string>
<string name="saved">Uloženo!</string>
<string name="field_mandatory">Chybí povinná pole. Chcete-li vyplnit soubor dat, vyplňte je prosím.</string>
<string name="field_required">Pokud nastavíte hodnotu, celý řádek potřebuje k dokončení datové sady všechny hodnoty.</string>
<string name="ok">OK</string>
<string name="dataset_saved_completed">Uloženo a dokončeno!</string>
<string name="run_validation_rules">Chcete zkontrolovat kvalitu dat?</string>
<string name="error">Chyba</string>
<string name="complete_anyway">Přesto dokončit</string>
<string name="review">Posouzení</string>

</resources>
17 changes: 17 additions & 0 deletions aggregates/src/commonMain/composeResources/values-es/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="validation_success_title">¡Parece que todo está bien!</string>
<string name="mark_dataset_complete">¿Quiere completar también el set de datos?</string>
<string name="not_now">Ahora no</string>
<string name="complete">Completar</string>
<string name="saved">¡Guardado!</string>
<string name="field_mandatory">Hay campos obligatorios vacíos. Por favor, rellénelos para poder completar el set de datos.</string>
<string name="field_required">Si introduce un valor, tendrá que completar toda la fila para poder marcar como Completado el Data Set.</string>
<string name="ok">Correcto</string>
<string name="dataset_saved_completed">¡Guardado y completado!</string>
<string name="run_validation_rules">¿Quiere validar la calidad de los datos?</string>
<string name="error">Error</string>
<string name="complete_anyway">Completar de todas formas</string>
<string name="review">Revisar</string>

</resources>
16 changes: 16 additions & 0 deletions aggregates/src/commonMain/composeResources/values-fr/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="validation_success_title">Tout a l\'air bien!</string>
<string name="mark_dataset_complete">Voulez-vous également compléter l\'ensemble de données?</string>
<string name="complete">Terminer</string>
<string name="saved">Enregistré!</string>
<string name="field_mandatory">Il manque des champs obligatoires. Veuillez les remplir pour compléter l\'ensemble de données.</string>
<string name="field_required">Si vous saisissez une valeur, la ligne entière doit être remplie pour compléter l\'ensemble de données.</string>
<string name="ok">Ok</string>
<string name="dataset_saved_completed">Enregistré et terminé!</string>
<string name="run_validation_rules">Voulez-vous vérifier la qualité des données?</string>
<string name="error">Erreur</string>
<string name="complete_anyway">Terminer quand même</string>
<string name="review">Vérifier</string>

</resources>
15 changes: 15 additions & 0 deletions aggregates/src/commonMain/composeResources/values-id/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="validation_success_title">Semuanya terlihat bagus!</string>
<string name="mark_dataset_complete">Apakah Anda juga ingin melengkapi data set?</string>
<string name="complete">Lengkap</string>
<string name="saved">Tersimpan!</string>
<string name="field_mandatory">Terdapat hal penting yang hilang. Harap mengisinya untuk melengkapi data.set</string>
<string name="field_required">Jika Anda mengisi, semua baris harus terisi untuk menyelesaikan data set</string>
<string name="ok">Ok</string>
<string name="dataset_saved_completed">Tersimpan dan selesai!</string>
<string name="run_validation_rules">Apakah Anda ingin memeriksa kualitas data?</string>
<string name="error">Kesalahan</string>
<string name="complete_anyway">Lengkap</string>

</resources>
15 changes: 15 additions & 0 deletions aggregates/src/commonMain/composeResources/values-lo/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="validation_success_title">ທຸກຢ່າງຮຽບຮ້ອຍດີ</string>
<string name="mark_dataset_complete">ທ່ານຕ້ອງການເຮັດຊຸດຂໍ້ມູນໃຫ້ຄົບຖ້ວນບໍ?</string>
<string name="not_now">ບໍ່​ແມ່ນ​ຕອນ​ນີ້</string>
<string name="complete">ສຳເລັດແລ້ວ</string>
<string name="saved">ບັນທຶກແລ້ວ!</string>
<string name="field_required">ຖ້າທ່ານຕັ້ງຄ່າ, ແຖວທັ້ງໝົດຕ້ອງໃຊ້ຄ່າທັ້ງໝົດເພື່ອເຮັດໃຫ້ຊຸດຂໍ້ມູນສົມບູນ</string>
<string name="ok">​ຕົກ​ລົງ</string>
<string name="dataset_saved_completed">ບັນ​ທຶກ​ແລະ​ສໍາ​ເລັດ​!</string>
<string name="run_validation_rules">ທ່ານຕ້ອງການກວດສອບຄຸນນະພາບຂໍ້ມູນນີ້ບໍ?</string>
<string name="error">ເກີດການຜິດພາດ</string>
<string name="review">ທົບທວນຄືນ</string>

</resources>
Loading