diff --git a/app/src/androidTest/java/org/dhis2/usescases/flow/teiFlow/TeiFlowTest.kt b/app/src/androidTest/java/org/dhis2/usescases/flow/teiFlow/TeiFlowTest.kt index e7f603a2f5..acfe77dd6c 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/flow/teiFlow/TeiFlowTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/flow/teiFlow/TeiFlowTest.kt @@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.rule.ActivityTestRule import org.dhis2.common.mockwebserver.MockWebServerRobot.Companion.API_OLD_TRACKED_ENTITY_PATH import org.dhis2.common.mockwebserver.MockWebServerRobot.Companion.API_OLD_TRACKED_ENTITY_RESPONSE +import org.dhis2.commons.date.DateUtils import org.dhis2.usescases.BaseTest import org.dhis2.usescases.flow.teiFlow.entity.DateRegistrationUIModel import org.dhis2.usescases.flow.teiFlow.entity.EnrollmentListUIModel @@ -16,7 +17,6 @@ import org.hisp.dhis.android.core.mockwebserver.ResponseController import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import java.text.SimpleDateFormat import java.util.Date @@ -95,9 +95,9 @@ class TeiFlowTest : BaseTest() { ) private fun getCurrentDate(): String { - val sdf = SimpleDateFormat(DATE_FORMAT) + val sdf = DateUtils.uiDateFormat() val dateFormat = sdf.format(Date()) - return dateFormat.removePrefix("0") + return dateFormat } private fun prepareWomanProgrammeIntentAndLaunchActivity(ruleSearch: ActivityTestRule) { @@ -117,7 +117,5 @@ class TeiFlowTest : BaseTest() { const val ORG_UNIT = "Ngelehun CHC" const val NAME = "Marta" const val LASTNAME = "Stuart" - - const val DATE_FORMAT = "dd/M/yyyy" } } \ No newline at end of file diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt index cdabba774d..4f12841ae7 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/ProgramEventTest.kt @@ -57,13 +57,13 @@ class ProgramEventTest : BaseTest() { } composeTestRule.waitForIdle() programEventsRobot(composeTestRule) { - checkEventWasCreatedAndClosed("1/1/2001") + checkEventWasCreatedAndClosed() } } @Test fun shouldOpenExistingEvent() { - val eventDate = "15/3/2020" + val eventDate = "15/03/2020" val eventOrgUnit = "Ngelehun CHC" prepareProgramAndLaunchActivity(antenatalCare) @@ -81,7 +81,7 @@ class ProgramEventTest : BaseTest() { @Ignore("Flaky test, will be look om issue ANDROAPP-6030") @Test fun shouldCompleteAnEventAndReopenIt() { - val eventDate = "15/3/2020" + val eventDate = "15/03/2020" prepareProgramAndLaunchActivity(antenatalCare) @@ -107,7 +107,7 @@ class ProgramEventTest : BaseTest() { @Test fun shouldDeleteEvent() { - val eventDate = "15/3/2020" + val eventDate = "15/03/2020" prepareProgramAndLaunchActivity(antenatalCare) diff --git a/app/src/androidTest/java/org/dhis2/usescases/programevent/robot/ProgramEventsRobot.kt b/app/src/androidTest/java/org/dhis2/usescases/programevent/robot/ProgramEventsRobot.kt index 896a920c72..9be1dff635 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/programevent/robot/ProgramEventsRobot.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/programevent/robot/ProgramEventsRobot.kt @@ -7,9 +7,7 @@ import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasText import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick -import androidx.compose.ui.test.printToLog import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches @@ -44,7 +42,7 @@ class ProgramEventsRobot(val composeTestRule: ComposeContentTestRule) : BaseRobo } @OptIn(ExperimentalTestApi::class) - fun checkEventWasCreatedAndClosed(eventDate: String) { + fun checkEventWasCreatedAndClosed() { composeTestRule.waitUntilAtLeastOneExists(hasTestTag("EVENT_ITEM")) composeTestRule.onNode( hasTestTag("EVENT_ITEM") diff --git a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt index 7b7d5c1fa6..df1d7a387e 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/searchte/SearchTETest.kt @@ -435,7 +435,7 @@ class SearchTETest : BaseTest() { private fun createDisplayListFields() = DisplayListFieldsUIModel( "Sarah", "Thompson", - "2001-01-01", + "01/01/2001", "sarah@gmail.com", "Main street 1", "56", diff --git a/app/src/main/java/org/dhis2/bindings/StringExtensions.kt b/app/src/main/java/org/dhis2/bindings/StringExtensions.kt index 026140e282..9e2dd7797f 100644 --- a/app/src/main/java/org/dhis2/bindings/StringExtensions.kt +++ b/app/src/main/java/org/dhis2/bindings/StringExtensions.kt @@ -1,8 +1,8 @@ package org.dhis2.bindings import android.content.Context +import org.dhis2.commons.date.DateUtils import org.dhis2.commons.date.toDateSpan -import org.dhis2.utils.DateUtils import timber.log.Timber import java.util.Date @@ -38,7 +38,7 @@ fun String.toDate(): Date { } if (date == null) { try { - date = DateUtils.databaseDateFormatMillis().parse(this) + date = DateUtils.databaseDateFormat().parse(this) } catch (e: Exception) { Timber.d("wrong format") } diff --git a/app/src/main/java/org/dhis2/usescases/datasets/dataSetTable/dataSetSection/MapFieldValueToUser.kt b/app/src/main/java/org/dhis2/usescases/datasets/dataSetTable/dataSetSection/MapFieldValueToUser.kt index ea27653e45..b122f9478f 100644 --- a/app/src/main/java/org/dhis2/usescases/datasets/dataSetTable/dataSetSection/MapFieldValueToUser.kt +++ b/app/src/main/java/org/dhis2/usescases/datasets/dataSetTable/dataSetSection/MapFieldValueToUser.kt @@ -2,9 +2,9 @@ package org.dhis2.usescases.datasets.dataSetTable.dataSetSection import org.dhis2.R import org.dhis2.bindings.toDate +import org.dhis2.commons.date.DateUtils import org.dhis2.commons.resources.ResourceManager import org.dhis2.data.forms.dataentry.tablefields.FieldViewModel -import org.dhis2.utils.DateUtils import org.hisp.dhis.android.core.common.ValueType import org.hisp.dhis.android.core.dataelement.DataElement diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java index 070bb93b60..98a36d230a 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchRepositoryImpl.java @@ -368,7 +368,7 @@ private void setAttributeValue(SearchTeiModel searchTei, TrackedEntitySearchItem String value = attribute.getValue(); String transformedValue; if (value != null) { - transformedValue = ValueUtils.transformValue(d2, value, attribute.getValueType(), attribute.getOptionSet()); + transformedValue = ValueUtils.Companion.transformValue(d2, value, attribute.getValueType(), attribute.getOptionSet()); } else { transformedValue = sortingValueSetter.getUnknownLabel(); } @@ -409,8 +409,8 @@ private void setOverdueEvents(@NonNull SearchTeiModel tei, Program selectedProgr if (count > 0) { tei.setHasOverdue(true); - Date scheduleDate = scheduleList.size() > 0 ? scheduleList.get(0).dueDate() : null; - Date overdueDate = overdueList.size() > 0 ? overdueList.get(0).dueDate() : null; + Date scheduleDate = !scheduleList.isEmpty() ? scheduleList.get(0).dueDate() : null; + Date overdueDate = !overdueList.isEmpty() ? overdueList.get(0).dueDate() : null; Date dateToShow = null; if (scheduleDate != null && overdueDate != null) { if (scheduleDate.before(overdueDate)) { @@ -530,8 +530,8 @@ private List getTETypeAttributeUids(String teTypeUid) { } private int getTeiDefaultRes(TrackedEntityInstance tei) { - TrackedEntityType teiType = d2.trackedEntityModule().trackedEntityTypes().uid(tei.trackedEntityType()).blockingGet(); - return resources.getObjectStyleDrawableResource(teiType.style().icon(), R.drawable.photo_temp_gray); + TrackedEntityType teiTypeValues = d2.trackedEntityModule().trackedEntityTypes().uid(tei.trackedEntityType()).blockingGet(); + return resources.getObjectStyleDrawableResource(teiTypeValues.style().icon(), R.drawable.photo_temp_gray); } private List getTrackedEntityAttributesForRelationship(TrackedEntityInstance tei, Program selectedProgram) { diff --git a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt index 3f5d68b3e7..2f580bc979 100644 --- a/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt +++ b/app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt @@ -18,7 +18,9 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.dhis2.R import org.dhis2.commons.data.SearchTeiModel -import org.dhis2.commons.date.DateUtils +import org.dhis2.commons.extensions.toFriendlyDate +import org.dhis2.commons.extensions.toFriendlyDateTime +import org.dhis2.commons.extensions.toPercentage import org.dhis2.commons.filters.FilterManager import org.dhis2.commons.idlingresource.SearchIdlingResourceSingleton import org.dhis2.commons.network.NetworkUtils @@ -38,7 +40,6 @@ import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.ValueType import org.hisp.dhis.android.core.maintenance.D2ErrorCode import timber.log.Timber -import java.text.ParseException const val TEI_TYPE_SEARCH_MAX_RESULTS = 5 @@ -223,7 +224,9 @@ class SearchTEIViewModel( SearchScreenState.LIST -> setListScreen() SearchScreenState.MAP -> setMapScreen() SearchScreenState.ANALYTICS -> setAnalyticsScreen() - else -> {} + else -> { + // no-op + } } } @@ -927,6 +930,7 @@ class SearchTEIViewModel( val map = mutableMapOf() uiState.items.filter { !it.value.isNullOrEmpty() } .forEach { item -> + when (item.valueType) { ValueType.ORGANISATION_UNIT, ValueType.MULTI_TEXT -> { map[item.uid] = (item.displayName ?: "") @@ -934,31 +938,13 @@ class SearchTEIViewModel( ValueType.DATE, ValueType.AGE -> { item.value?.let { - if (it.isNotEmpty()) { - val date = try { - DateUtils.oldUiDateFormat().parse(it) - } catch (e: ParseException) { - null - } - map[item.uid] = date?.let { - DateUtils.uiDateFormat().format(date) - } ?: it - } + map[item.uid] = it.toFriendlyDate() } } ValueType.DATETIME -> { item.value?.let { - if (it.isNotEmpty()) { - val date = try { - DateUtils.databaseDateFormatNoSeconds().parse(it) - } catch (e: ParseException) { - null - } - map[item.uid] = date?.let { - DateUtils.uiDateTimeFormat().format(date) - } ?: it - } + map[item.uid] = it.toFriendlyDateTime() } } @@ -975,7 +961,9 @@ class SearchTEIViewModel( } ValueType.PERCENTAGE -> { - map[item.uid] = "${item.value}%" + item.value?.let { + map[item.uid] = it.toPercentage() + } } else -> { diff --git a/app/src/main/java/org/dhis2/usescases/teiDashboard/DashboardRepositoryImpl.kt b/app/src/main/java/org/dhis2/usescases/teiDashboard/DashboardRepositoryImpl.kt index a123aa9781..d81101aa2d 100644 --- a/app/src/main/java/org/dhis2/usescases/teiDashboard/DashboardRepositoryImpl.kt +++ b/app/src/main/java/org/dhis2/usescases/teiDashboard/DashboardRepositoryImpl.kt @@ -97,53 +97,42 @@ class DashboardRepositoryImpl( teiUid, ) .map> { attributesValues: List -> - val formattedValues: MutableList = - java.util.ArrayList() - for (attributeValue in attributesValues) { - if (attributeValue.value() != null) { - val attribute = - d2.trackedEntityModule().trackedEntityAttributes() - .uid(attributeValue.trackedEntityAttribute()).blockingGet() - if (attribute!!.valueType() != ValueType.IMAGE) { - formattedValues.add( - ValueUtils.transform( - d2, - attributeValue, - attribute!!.valueType(), - if (attribute!!.optionSet() != null) { - attribute!!.optionSet()!! - .uid() - } else { - null - }, - ), - ) - } - } else { - formattedValues.add( - TrackedEntityAttributeValue.builder() - .trackedEntityAttribute(attributeValue.trackedEntityAttribute()) - .trackedEntityInstance(teiUid) - .value("") - .build(), - ) - } - } + val formattedValues = formatProgramAttributeValues(attributesValues) formattedValues }.toObservable() } else { val teType = d2.trackedEntityModule().trackedEntityInstances().uid(teiUid).blockingGet()!! .trackedEntityType() - val attributeValues: MutableList = java.util.ArrayList() - for (attributeValue in teiAttributesProvider.getValuesFromTrackedEntityTypeAttributes( - teType, - teiUid, - )) { - val attribute = d2.trackedEntityModule().trackedEntityAttributes() - .uid(attributeValue.trackedEntityAttribute()).blockingGet() - if (attribute!!.valueType() != ValueType.IMAGE && attributeValue.value() != null) { - attributeValues.add( + + val attributeValues = mapTeiTypeAttributeValues( + teiAttributesProvider.getValuesFromTrackedEntityTypeAttributes( + teType, + teiUid, + ), + ) + if (attributeValues.isEmpty()) { + formatProgramAttributeValuesByTrackedEntity( + attributeValues, + teiAttributesProvider.getValuesFromProgramTrackedEntityAttributes( + teType, + teiUid, + ), + ) + } + Observable.just(attributeValues) + } + } + + private fun formatProgramAttributeValues(list: List): MutableList { + val formattedValues: MutableList = mutableListOf() + for (attributeValue in list) { + if (attributeValue.value() != null) { + val attribute = + d2.trackedEntityModule().trackedEntityAttributes() + .uid(attributeValue.trackedEntityAttribute()).blockingGet() + if (attribute!!.valueType() != ValueType.IMAGE) { + formattedValues.add( ValueUtils.transform( d2, attributeValue, @@ -157,31 +146,103 @@ class DashboardRepositoryImpl( ), ) } + } else { + formattedValues.add( + TrackedEntityAttributeValue.builder() + .trackedEntityAttribute(attributeValue.trackedEntityAttribute()) + .trackedEntityInstance(teiUid) + .value("") + .build(), + ) } - if (attributeValues.isEmpty()) { - for (attributeValue in teiAttributesProvider.getValuesFromProgramTrackedEntityAttributes( - teType, - teiUid, - )) { - val attribute = d2.trackedEntityModule().trackedEntityAttributes() - .uid(attributeValue.trackedEntityAttribute()).blockingGet() - attributeValues.add( - ValueUtils.transform( - d2, - attributeValue, - attribute!!.valueType(), - if (attribute.optionSet() != null) { - attribute.optionSet()!! - .uid() - } else { - null - }, + } + return formattedValues + } + + private fun formatProgramAttributeValuesByTrackedEntity( + formattedList: MutableList, + list: List, + ): MutableList { + for (attributeValue in list) { + val attribute = d2.trackedEntityModule().trackedEntityAttributes() + .uid(attributeValue.trackedEntityAttribute()).blockingGet() + formattedList.add( + ValueUtils.transform( + d2, + attributeValue, + attribute!!.valueType(), + if (attribute.optionSet() != null) { + attribute.optionSet()!! + .uid() + } else { + null + }, + ), + ) + } + return formattedList + } + + private fun mapTeiTypeAttributeValues(list: List): MutableList { + val attributeValues: MutableList = mutableListOf() + for (attributeValue in list) { + val attribute = d2.trackedEntityModule().trackedEntityAttributes() + .uid(attributeValue.trackedEntityAttribute()).blockingGet() + if (attribute!!.valueType() != ValueType.IMAGE && attributeValue.value() != null) { + attributeValues.add( + ValueUtils.transform( + d2, + attributeValue, + attribute.valueType(), + if (attribute.optionSet() != null) { + attribute.optionSet()!! + .uid() + } else { + null + }, + ), + ) + } + } + + return attributeValues + } + + private fun mapRelationShipTypes(list: List, teType: String): MutableList> { + val relTypeList: MutableList> = + java.util.ArrayList() + for (relationshipType in list) { + if (relationshipType.fromConstraint() != null && relationshipType.fromConstraint()!! + .trackedEntityType() != null && relationshipType.fromConstraint()!! + .trackedEntityType()!!.uid() == teType + ) { + if (relationshipType.toConstraint() != null && relationshipType.toConstraint()!! + .trackedEntityType() != null + ) { + relTypeList.add( + Pair.create( + relationshipType, + relationshipType.toConstraint()!! + .trackedEntityType()!!.uid(), ), ) } + } else if (relationshipType.bidirectional()!! && relationshipType.toConstraint() != null && relationshipType.toConstraint()!! + .trackedEntityType() != null && relationshipType.toConstraint()!! + .trackedEntityType()!! + .uid() == teType && relationshipType.fromConstraint() != null && + relationshipType.fromConstraint()!!.trackedEntityType() != null + ) { + relTypeList.add( + Pair.create( + relationshipType, + relationshipType.fromConstraint()!! + .trackedEntityType()!!.uid(), + ), + ) } - Observable.just(attributeValues) } + return relTypeList } override fun setFollowUp(enrollmentUid: String?): Boolean { @@ -228,8 +289,8 @@ class DashboardRepositoryImpl( return d2.systemInfoModule().systemInfo().get().toObservable() .map(Function { obj: SystemInfo -> obj.version() }) .flatMap { version: String? -> - if (version == "2.29") { - return@flatMap d2.relationshipModule().relationshipTypes() + return@flatMap if (version == "2.29") { + d2.relationshipModule().relationshipTypes() .get().toObservable() .flatMapIterable { list: List? -> list } .map> { relationshipType: RelationshipType? -> @@ -239,45 +300,10 @@ class DashboardRepositoryImpl( ) }.toList().toObservable() } else { - return@flatMap d2.relationshipModule() + d2.relationshipModule() .relationshipTypes().withConstraints().get() .map>> { relationshipTypes: List -> - val relTypeList: MutableList> = - java.util.ArrayList() - for (relationshipType in relationshipTypes) { - if (relationshipType.fromConstraint() != null && relationshipType.fromConstraint()!! - .trackedEntityType() != null && relationshipType.fromConstraint()!! - .trackedEntityType()!!.uid() == teType - ) { - if (relationshipType.toConstraint() != null && relationshipType.toConstraint()!! - .trackedEntityType() != null - ) { - relTypeList.add( - Pair.create( - relationshipType, - relationshipType.toConstraint()!! - .trackedEntityType()!!.uid(), - ), - ) - } - } else if (relationshipType.bidirectional()!! && relationshipType.toConstraint() != null && relationshipType.toConstraint()!! - .trackedEntityType() != null && relationshipType.toConstraint()!! - .trackedEntityType()!! - .uid() == teType - ) { - if (relationshipType.fromConstraint() != null && relationshipType.fromConstraint()!! - .trackedEntityType() != null - ) { - relTypeList.add( - Pair.create( - relationshipType, - relationshipType.fromConstraint()!! - .trackedEntityType()!!.uid(), - ), - ) - } - } - } + val relTypeList = mapRelationShipTypes(relationshipTypes, teType) relTypeList.toList() }.toObservable() } @@ -412,7 +438,7 @@ class DashboardRepositoryImpl( .trackedEntityInstances() .uid(teiUid) .blockingGet() - ?.state() == State.TO_POST + ?.aggregatedSyncState() == State.TO_POST val hasAuthority = d2.userModule() .authorities() .byName().eq("F_TEI_CASCADE_DELETE") @@ -433,7 +459,7 @@ class DashboardRepositoryImpl( val local = d2.enrollmentModule() .enrollments() .uid(enrollmentUid) - .blockingGet()!!.state() == State.TO_POST + .blockingGet()!!.aggregatedSyncState() == State.TO_POST val hasAuthority = d2.userModule() .authorities() .byName().eq("F_ENROLLMENT_CASCADE_DELETE") @@ -451,9 +477,9 @@ class DashboardRepositoryImpl( enrollmentObjectRepository.blockingGet()!!.status()!!, ) enrollmentObjectRepository.blockingDelete() - !d2.enrollmentModule().enrollments().byTrackedEntityInstance().eq(teiUid) + d2.enrollmentModule().enrollments().byTrackedEntityInstance().eq(teiUid) .byDeleted().isFalse - .byStatus().eq(EnrollmentStatus.ACTIVE).blockingGet().isEmpty() + .byStatus().eq(EnrollmentStatus.ACTIVE).blockingGet().isNotEmpty() } } diff --git a/app/src/main/java/org/dhis2/usescases/teiDashboard/teiProgramList/TeiProgramListRepositoryImpl.java b/app/src/main/java/org/dhis2/usescases/teiDashboard/teiProgramList/TeiProgramListRepositoryImpl.java index 973e128a50..ece43b5b34 100644 --- a/app/src/main/java/org/dhis2/usescases/teiDashboard/teiProgramList/TeiProgramListRepositoryImpl.java +++ b/app/src/main/java/org/dhis2/usescases/teiDashboard/teiProgramList/TeiProgramListRepositoryImpl.java @@ -2,20 +2,17 @@ import androidx.annotation.NonNull; -import org.dhis2.R; +import org.dhis2.commons.date.DateUtils; import org.dhis2.commons.resources.MetadataIconProvider; -import org.dhis2.commons.resources.ResourceManager; import org.dhis2.usescases.main.program.ProgramDownloadState; import org.dhis2.usescases.main.program.ProgramViewModel; import org.dhis2.usescases.main.program.ProgramViewModelMapper; -import org.dhis2.utils.DateUtils; import org.hisp.dhis.android.core.D2; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.EnrollmentCreateProjection; import org.hisp.dhis.android.core.enrollment.EnrollmentStatus; import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; import org.hisp.dhis.android.core.program.Program; -import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor; import java.util.ArrayList; import java.util.Collections; diff --git a/app/src/main/java/org/dhis2/utils/ValueUtils.java b/app/src/main/java/org/dhis2/utils/ValueUtils.java deleted file mode 100644 index 5952d55ef5..0000000000 --- a/app/src/main/java/org/dhis2/utils/ValueUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.dhis2.utils; - -import org.hisp.dhis.android.core.D2; -import org.hisp.dhis.android.core.common.ValueType; -import org.hisp.dhis.android.core.option.Option; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue; - -import java.util.Objects; - -/** - * QUADRAM. Created by ppajuelo on 25/09/2018. - */ - -public class ValueUtils { - - private ValueUtils() { - throw new IllegalStateException("Utility class"); - } - - public static TrackedEntityAttributeValue transform(D2 d2, TrackedEntityAttributeValue attributeValue, ValueType valueType, String optionSetUid) { - String transformedValue = transformValue(d2, attributeValue.value(), valueType, optionSetUid); - - if (!Objects.equals(transformedValue, attributeValue.value())) { - return attributeValue.toBuilder() - .value(transformedValue) - .build(); - } else { - return attributeValue; - } - } - - public static String transformValue(D2 d2, String value, ValueType valueType, String optionSetUid) { - String teAttrValue = value; - if (valueType.equals(ValueType.ORGANISATION_UNIT)) { - if (!d2.organisationUnitModule().organisationUnits().byUid().eq(value).blockingIsEmpty()) { - String orgUnitName = d2.organisationUnitModule().organisationUnits() - .byUid().eq(value) - .one().blockingGet().displayName(); - teAttrValue = orgUnitName; - } - } else if (optionSetUid != null) { - String optionCode = value; - if (optionCode != null) { - Option option = d2.optionModule().options().byOptionSetUid().eq(optionSetUid).byCode().eq(optionCode).one().blockingGet(); - if (option != null && (Objects.equals(option.code(), optionCode) || Objects.equals(option.name(), optionCode))) { - teAttrValue = option.displayName(); - } - } - } - return teAttrValue; - } -} diff --git a/app/src/main/java/org/dhis2/utils/ValueUtils.kt b/app/src/main/java/org/dhis2/utils/ValueUtils.kt new file mode 100644 index 0000000000..ff41fc0a4f --- /dev/null +++ b/app/src/main/java/org/dhis2/utils/ValueUtils.kt @@ -0,0 +1,88 @@ +package org.dhis2.utils + +import org.dhis2.commons.extensions.toFriendlyDate +import org.dhis2.commons.extensions.toFriendlyDateTime +import org.dhis2.commons.extensions.toPercentage +import org.hisp.dhis.android.core.D2 +import org.hisp.dhis.android.core.common.ValueType +import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue + +/** + * QUADRAM. Created by ppajuelo on 25/09/2018. + */ +class ValueUtils private constructor() { + init { + throw IllegalStateException("Utility class") + } + + companion object { + fun transform( + d2: D2, + attributeValue: TrackedEntityAttributeValue, + valueType: ValueType?, + optionSetUid: String?, + ): TrackedEntityAttributeValue { + val transformedValue = + transformValue(d2, attributeValue.value(), valueType, optionSetUid) + + return if (transformedValue != attributeValue.value()) { + attributeValue.toBuilder() + .value(transformedValue) + .build() + } else { + attributeValue + } + } + + fun transformValue( + d2: D2, + value: String?, + valueType: ValueType?, + optionSetUid: String?, + ): String? { + var teAttrValue = value + when (valueType) { + ValueType.ORGANISATION_UNIT -> { + if (!d2.organisationUnitModule().organisationUnits().byUid().eq(value) + .blockingIsEmpty() + ) { + val orgUnitName = d2.organisationUnitModule().organisationUnits() + .byUid().eq(value) + .one().blockingGet()!!.displayName()!! + teAttrValue = orgUnitName + } + } + ValueType.DATE, ValueType.AGE -> { + teAttrValue = teAttrValue?.toFriendlyDate() + } + ValueType.DATETIME -> { + teAttrValue = teAttrValue?.toFriendlyDateTime() + } + + ValueType.PERCENTAGE -> { + teAttrValue = teAttrValue?.toPercentage() + } + else -> { + teAttrValue = transformOptionSet(optionSetUid, d2, value) + } + } + return teAttrValue + } + + private fun transformOptionSet(optionSetUid: String?, d2: D2, value: String?): String? { + var teAttrValue = value + if (optionSetUid != null) { + val optionCode = value + if (optionCode != null) { + val option = + d2.optionModule().options().byOptionSetUid().eq(optionSetUid).byCode() + .eq(optionCode).one().blockingGet() + if (option != null && (option.code() == optionCode || option.name() == optionCode)) { + teAttrValue = option.displayName() + } + } + } + return teAttrValue + } + } +} diff --git a/app/src/test/java/org/dhis2/data/dhislogic/DhisPeriodUtilsTest.kt b/app/src/test/java/org/dhis2/data/dhislogic/DhisPeriodUtilsTest.kt index 1dfe083851..1116d9637e 100644 --- a/app/src/test/java/org/dhis2/data/dhislogic/DhisPeriodUtilsTest.kt +++ b/app/src/test/java/org/dhis2/data/dhislogic/DhisPeriodUtilsTest.kt @@ -47,7 +47,7 @@ class DhisPeriodUtilsTest { .build() Assert.assertEquals( - "11/1/2019", + "11/01/2019", periodUtils.getPeriodUIString(null, testDate, Locale.ENGLISH), ) } @@ -66,7 +66,7 @@ class DhisPeriodUtilsTest { .build() Assert.assertEquals( - "11/1/2019", + "11/01/2019", periodUtils.getPeriodUIString( PeriodType.Daily, testDate, diff --git a/app/src/test/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/domain/ConfigureEventReportDateTest.kt b/app/src/test/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/domain/ConfigureEventReportDateTest.kt index c354f8702f..4b521c9ce6 100644 --- a/app/src/test/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/domain/ConfigureEventReportDateTest.kt +++ b/app/src/test/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/domain/ConfigureEventReportDateTest.kt @@ -45,7 +45,7 @@ class ConfigureEventReportDateTest { ) // And has a concrete date - val expectedDate = "14/2/2022" + val expectedDate = "14/02/2022" val event: Event = mock { on { eventDate() } doReturn DateUtils.uiDateFormat().parse(expectedDate) @@ -97,7 +97,7 @@ class ConfigureEventReportDateTest { periodUtils = periodUtils, ) - val tomorrow = "16/2/2022" + val tomorrow = "16/02/2022" whenever( periodUtils.getPeriodUIString(any(), any(), any()), @@ -122,8 +122,8 @@ class ConfigureEventReportDateTest { scheduleInterval = 6, ) - val lastEventDate = "13/2/2022" - val nextEventDate = "19/2/2022" + val lastEventDate = "13/02/2022" + val nextEventDate = "19/02/2022" whenever( repository.getStageLastDate(ENROLLMENT_ID), ) doReturn DateUtils.uiDateFormat().parse(lastEventDate) @@ -147,8 +147,8 @@ class ConfigureEventReportDateTest { scheduleInterval = 6, ) - val lastEventDate = "13/2/2022" - val nextEventDate = "19/2/2022" + val lastEventDate = "13/02/2022" + val nextEventDate = "19/02/2022" whenever( repository.getStageLastDate(ENROLLMENT_ID), ) doReturn null @@ -180,8 +180,8 @@ class ConfigureEventReportDateTest { enrollmentId = ENROLLMENT_ID, ) - val lastEventDate = "13/2/2022" - val nextEventDate = "15/2/2022" + val lastEventDate = "13/02/2022" + val nextEventDate = "15/02/2022" whenever( repository.getStageLastDate(ENROLLMENT_ID), ) doReturn null diff --git a/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt b/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt index 143ca66547..73e510c82b 100644 --- a/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt +++ b/app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt @@ -638,8 +638,8 @@ class SearchTEIViewModelTest { val expectedMap = mapOf( "uid1" to "Friendly OrgUnit Name", "uid2" to "Male", - "uid3" to "21/2/2024", - "uid4" to "21/2/2024 01:00", + "uid3" to "21/02/2024", + "uid4" to "21/02/2024 - 01:00", "uid5" to "Boolean: false", "uid6" to "Yes Only", "uid7" to "Text value", diff --git a/commons/src/main/java/org/dhis2/commons/bindings/ValueExtensions.kt b/commons/src/main/java/org/dhis2/commons/bindings/ValueExtensions.kt index 85c0602f01..48586b7653 100644 --- a/commons/src/main/java/org/dhis2/commons/bindings/ValueExtensions.kt +++ b/commons/src/main/java/org/dhis2/commons/bindings/ValueExtensions.kt @@ -1,6 +1,7 @@ package org.dhis2.bindings import org.dhis2.commons.date.DateUtils +import org.dhis2.commons.extensions.toPercentage import org.hisp.dhis.android.core.D2 import org.hisp.dhis.android.core.common.ValueType import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue @@ -71,13 +72,13 @@ fun checkValueTypeValue(d2: D2, valueType: ValueType?, value: String): String { ValueType.IMAGE, ValueType.FILE_RESOURCE -> d2.fileResourceModule().fileResources().uid(value).blockingGet()?.path() ?: "" - ValueType.DATE -> + ValueType.DATE, ValueType.AGE -> DateUtils.uiDateFormat().format( DateUtils.oldUiDateFormat().parse(value) ?: "", ) ValueType.DATETIME -> - DateUtils.dateTimeFormat().format( + DateUtils.uiDateTimeFormat().format( DateUtils.databaseDateFormatNoSeconds().parse(value) ?: "", ) @@ -86,6 +87,8 @@ fun checkValueTypeValue(d2: D2, valueType: ValueType?, value: String): String { DateUtils.timeFormat().parse(value) ?: "", ) + ValueType.PERCENTAGE -> value.toPercentage() + else -> value } } diff --git a/commons/src/main/java/org/dhis2/commons/data/SearchTeiModel.java b/commons/src/main/java/org/dhis2/commons/data/SearchTeiModel.java index d3c9597a70..ba8d33d93c 100644 --- a/commons/src/main/java/org/dhis2/commons/data/SearchTeiModel.java +++ b/commons/src/main/java/org/dhis2/commons/data/SearchTeiModel.java @@ -1,7 +1,5 @@ package org.dhis2.commons.data; -import androidx.compose.ui.graphics.Color; - import org.dhis2.commons.data.tuples.Trio; import org.dhis2.ui.MetadataIconData; import org.hisp.dhis.android.core.enrollment.Enrollment; @@ -9,7 +7,6 @@ import org.hisp.dhis.android.core.program.Program; import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue; import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.mobile.ui.designsystem.component.internal.ImageCardData; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/commons/src/main/java/org/dhis2/commons/date/DateExtensions.kt b/commons/src/main/java/org/dhis2/commons/date/DateExtensions.kt index 17b532a446..e8e0275fed 100644 --- a/commons/src/main/java/org/dhis2/commons/date/DateExtensions.kt +++ b/commons/src/main/java/org/dhis2/commons/date/DateExtensions.kt @@ -155,4 +155,4 @@ private fun getString( } fun Date?.toUi(): String? = - this?.let { SimpleDateFormat("d/M/yyyy", Locale.getDefault()).format(this) } + this?.let { DateUtils.uiDateFormat().format(this) } diff --git a/commons/src/main/java/org/dhis2/commons/date/DateUtils.java b/commons/src/main/java/org/dhis2/commons/date/DateUtils.java index 542380e0ed..362c9b89eb 100644 --- a/commons/src/main/java/org/dhis2/commons/date/DateUtils.java +++ b/commons/src/main/java/org/dhis2/commons/date/DateUtils.java @@ -43,10 +43,10 @@ public static DateUtils getInstance() { public static final String WEEKLY_FORMAT_EXPRESSION = "w yyyy"; public static final String MONTHLY_FORMAT_EXPRESSION = "MMM yyyy"; public static final String YEARLY_FORMAT_EXPRESSION = "yyyy"; - public static final String SIMPLE_DATE_FORMAT = "d/M/yyyy"; + public static final String SIMPLE_DATE_FORMAT = "dd/MM/yyyy"; public static final String TIME_12H_EXPRESSION = "hh:mm a"; public static final String UI_LIBRARY_FORMAT = "ddMMyyyy"; - public static final String SIMPLE_DATE_TIME_FORMAT = "d/M/yyyy HH:mm"; + public static final String SIMPLE_DATE_TIME_FORMAT = "dd/MM/yyyy - HH:mm"; public Date[] getDateFromDateAndPeriod(Date date, Period period) { switch (period) { diff --git a/commons/src/main/java/org/dhis2/commons/extensions/StringExtensions.kt b/commons/src/main/java/org/dhis2/commons/extensions/StringExtensions.kt index fcf9df3202..f14ca437ea 100644 --- a/commons/src/main/java/org/dhis2/commons/extensions/StringExtensions.kt +++ b/commons/src/main/java/org/dhis2/commons/extensions/StringExtensions.kt @@ -2,27 +2,29 @@ package org.dhis2.commons.extensions import org.dhis2.commons.date.DateUtils import timber.log.Timber +import java.text.ParseException import java.util.Date fun String.toDate(): Date? { + val wrongFormat = "wrong format" var date: Date? = null try { date = DateUtils.databaseDateFormat().parse(this) } catch (e: Exception) { - Timber.d("wrong format") + Timber.d(wrongFormat) } if (date == null) { try { date = DateUtils.dateTimeFormat().parse(this) } catch (e: Exception) { - Timber.d("wrong format") + Timber.d(wrongFormat) } } if (date == null) { try { date = DateUtils.uiDateFormat().parse(this) } catch (e: Exception) { - Timber.d("wrong format") + Timber.d(wrongFormat) } } @@ -30,9 +32,47 @@ fun String.toDate(): Date? { try { date = DateUtils.oldUiDateFormat().parse(this) } catch (e: Exception) { - Timber.d("wrong format") + Timber.d(wrongFormat) } } return date } + +fun String.toPercentage(): String { + return "$this%" +} + +fun String.toFriendlyDate(): String { + return if (this.isNotEmpty()) { + var formattedDate = this + val date = try { + DateUtils.oldUiDateFormat().parse(this) + } catch (e: ParseException) { + null + } + date?.let { + formattedDate = DateUtils.uiDateFormat().format(date) + } + formattedDate + } else { + this + } +} + +fun String.toFriendlyDateTime(): String { + return if (this.isNotEmpty()) { + var formattedDate = this + val date = try { + DateUtils.databaseDateFormatNoSeconds().parse(this) + } catch (e: ParseException) { + null + } + date?.let { + formattedDate = DateUtils.uiDateTimeFormat().format(date) + } + formattedDate + } else { + this + } +} diff --git a/commons/src/main/java/org/dhis2/commons/resources/DhisPeriodUtils.kt b/commons/src/main/java/org/dhis2/commons/resources/DhisPeriodUtils.kt index 153a851d34..a9e53c2be2 100644 --- a/commons/src/main/java/org/dhis2/commons/resources/DhisPeriodUtils.kt +++ b/commons/src/main/java/org/dhis2/commons/resources/DhisPeriodUtils.kt @@ -11,7 +11,7 @@ import java.util.regex.Pattern const val DATE_FORMAT_EXPRESSION = "yyyy-MM-dd" const val MONTHLY_FORMAT_EXPRESSION = "MMM yyyy" const val YEARLY_FORMAT_EXPRESSION = "yyyy" -const val SIMPLE_DATE_FORMAT = "d/M/yyyy" +const val SIMPLE_DATE_FORMAT = "dd/MM/yyyy" class DhisPeriodUtils( d2: D2,