Skip to content

Identification features#25

Merged
alex-vt merged 17 commits intomainfrom
identification-features
Apr 16, 2026
Merged

Identification features#25
alex-vt merged 17 commits intomainfrom
identification-features

Conversation

@alex-vt
Copy link
Copy Markdown
Collaborator

@alex-vt alex-vt commented Apr 8, 2026

Features included:

  • Identification+ Enrol Last
  • Identification Confirm Identity
  • ModuleID in Identification
  • Identification result ordering by score

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds Simprints “Identification” capabilities across Search and Enrollment flows, including Enrol Last (register last biometrics after a new enrollment save), Confirm Identity gating before dashboard navigation, overriding moduleId for identification intents, and ordering biometric identification results by score/response order.

Changes:

  • Introduces Simprints session/state handling, intent utilities, D2 access wrapper, and use-cases to drive Enrol Last, Confirm Identity, and ordered results.
  • Integrates Simprints flows into Search (navigation + ordered paging) and Enrollment (finish interception + register-last result persistence).
  • Updates Form custom-intent handling to display pending placeholders and treat pending Enrol Last as “completed” for validation/completion.

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Expands fork README change log to include new Identification features.
form/src/test/java/org/dhis2/form/simprints/SimprintsCustomIntentFormPresenterTest.kt Adds unit tests for the new form presenter behavior.
form/src/test/java/org/dhis2/form/data/FormRepositoryImplTest.kt Adds coverage for treating pending Enrol Last values as completed/valid.
form/src/main/res/values/strings.xml Adds placeholder string for “from last biometric search”.
form/src/main/java/org/dhis2/form/ui/provider/inputfield/CustomIntentProvider.kt Adds Simprints-aware launch/result handling and pending placeholder UX for custom intents.
form/src/main/java/org/dhis2/form/simprints/SimprintsRememberCustomIntentFormPresenter.kt Adds Compose helper to build the Simprints form presenter with remembered state.
form/src/main/java/org/dhis2/form/simprints/SimprintsCustomIntentFormPresenter.kt Adds presenter to unify Simprints custom-intent launch/result/session behavior for forms.
form/src/main/java/org/dhis2/form/di/Injector.kt Adds provider for SimprintsSessionRepository in the form module.
form/src/main/java/org/dhis2/form/data/FormRepositoryImpl.kt Treats pending Simprints register-last as “completed” for section completion and mandatory validation.
commonskmm/src/androidMain/kotlin/org/dhis2/mobile/commons/customintents/CustomIntentRepositoryImpl.kt Overrides moduleId for Simprints identification request params using the user org unit.
commons/src/test/kotlin/org/dhis2/commons/simprints/utils/SimprintsSearchUtilsTest.kt Adds tests for biometric search detection and query filtering.
commons/src/test/kotlin/org/dhis2/commons/simprints/utils/SimprintsIntentUtilsTest.kt Adds tests for pending-value detection, display values, and session extraction.
commons/src/test/kotlin/org/dhis2/commons/simprints/usecases/SimprintsResolvePendingEnrollmentActionUseCaseTest.kt Adds tests for resolving a pending register-last action at enrollment finish.
commons/src/test/kotlin/org/dhis2/commons/simprints/usecases/SimprintsResolveConfirmIdentityCalloutUseCaseTest.kt Adds tests for resolving confirm-identity callouts.
commons/src/test/kotlin/org/dhis2/commons/simprints/usecases/SimprintsOrderSearchResultsByIdentifyResponseUseCaseTest.kt Adds tests for ordering TEI search results by identify response order.
commons/src/test/kotlin/org/dhis2/commons/simprints/repository/SimprintsSessionRepositoryTest.kt Adds tests for session/pending enrollment preference persistence.
commons/src/test/kotlin/org/dhis2/commons/simprints/repository/SimprintsD2RepositoryTest.kt Adds tests for the D2 wrapper used by Simprints flows.
commons/src/main/java/org/dhis2/commons/simprints/utils/SimprintsSearchUtils.kt Adds biometric search state derivation and query filtering utilities.
commons/src/main/java/org/dhis2/commons/simprints/utils/SimprintsIntentUtils.kt Adds Simprints callout detection, intent preparation, and pending placeholder helpers.
commons/src/main/java/org/dhis2/commons/simprints/usecases/SimprintsResolvePendingEnrollmentActionUseCase.kt Adds use-case to resolve/register last biometrics callout for pending enrollment.
commons/src/main/java/org/dhis2/commons/simprints/usecases/SimprintsResolveConfirmIdentityCalloutUseCase.kt Adds use-case to prepare confirm-identity callout for a selected TEI.
commons/src/main/java/org/dhis2/commons/simprints/usecases/SimprintsOrderSearchResultsByIdentifyResponseUseCase.kt Adds use-case to order TEI results to match identification response order.
commons/src/main/java/org/dhis2/commons/simprints/repository/SimprintsSessionRepository.kt Adds preference-backed session and pending-enrollment state repository.
commons/src/main/java/org/dhis2/commons/simprints/repository/SimprintsD2Repository.kt Adds D2 wrapper for enrollment context and TEA value read/write used by Simprints flows.
app/src/test/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModelTest.kt Adds tests for ordered biometric results and confirm-identity navigation events.
app/src/test/java/org/dhis2/usescases/enrollment/EnrollmentPresenterImplTest.kt Adds tests ensuring enrollment presenter delegates to Simprints enrollment view model.
app/src/test/java/org/dhis2/simprints/SimprintsSearchViewModelTest.kt Adds tests for confirm-identity gating and “use last biometrics” label state.
app/src/test/java/org/dhis2/simprints/SimprintsEnrollmentViewModelTest.kt Adds tests for Enrol Last launch/result persistence and error handling.
app/src/test/java/org/dhis2/simprints/SimprintsCustomIntentResultMapperTest.kt Adds tests for mapping custom-intent result data into stored values.
app/src/main/res/values/strings.xml Adds “New %s with last biometrics” label for create button.
app/src/main/java/org/dhis2/usescases/searchTrackEntity/ui/SearchTEUi.kt Updates create button label based on pending biometric session state.
app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEModule.java Wires Simprints repositories/use-cases/view-models into Search DI graph.
app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTeiViewModelFactory.kt Passes Simprints dependencies into SearchTEIViewModel.
app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEIViewModel.kt Adds Simprints navigation channel, “use last biometrics” state, confirm-identity handling, and ordered-result loading.
app/src/main/java/org/dhis2/usescases/searchTrackEntity/SearchTEActivity.kt Registers and handles confirm-identity launcher and bridges Simprints navigation actions.
app/src/main/java/org/dhis2/usescases/searchTrackEntity/listView/SearchTEList.kt Observes and passes Simprints label state into the create button composable.
app/src/main/java/org/dhis2/usescases/enrollment/EnrollmentPresenterImpl.kt Delegates finish/register-last flows to Simprints enrollment view model.
app/src/main/java/org/dhis2/usescases/enrollment/EnrollmentModule.kt Adds DI providers for Simprints enrollment flow components.
app/src/main/java/org/dhis2/usescases/enrollment/EnrollmentActivity.kt Intercepts finish to optionally launch register-last biometrics and persist results before finishing.
app/src/main/java/org/dhis2/simprints/SimprintsSearchViewModel.kt Implements confirm-identity gating and “use last biometrics” label behavior.
app/src/main/java/org/dhis2/simprints/SimprintsEnrollmentViewModel.kt Implements pending Enrol Last resolution and save-time persistence of returned values.
app/src/main/java/org/dhis2/simprints/SimprintsCustomIntentResultMapper.kt Adds mapper for extracting/joining returned values via the existing contract.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread form/src/test/java/org/dhis2/form/data/FormRepositoryImplTest.kt
@alex-vt alex-vt marked this pull request as ready for review April 8, 2026 15:02
@TristramN TristramN self-requested a review April 16, 2026 08:08
Copy link
Copy Markdown
Collaborator

@TristramN TristramN left a comment

Choose a reason for hiding this comment

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

Good to go but def extend VM and tackle the thread safety issue with the class wide var in the two VMs.

ERROR,
}

private var pendingAction: SimprintsResolvePendingEnrollmentActionUseCase.PendingEnrollmentAction? = null
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Having a var accessed by coroutines is a threading issue. If two coroutines interleave, both could read the same non-null value. You could use a mutex but in this case I'd recommend an atomic reference as this is more of a set and get holder.

) : DashboardAction()
}

private var pendingDashboardNavigation: PendingDashboardNavigation? = null
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is the same as the other class wide var in the other VM.

val searchState = SimprintsSearchUtils.searchState(searchFields)
val hasPendingSession = sessionRepository.hasPendingSession()
if (hasPendingSession && searchState.shouldClearPendingSession) {
sessionRepository.clear()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clearing the session state in a function called ShouldUseLastX is a bit confusing as it feels like a side effect. You call this to find out if you should use the label, but then without knowing it the session is cleared. I'd either change the name to be more explicit, or just split this function into 2:

fun clearPendingSessionIfNeeded(searchFields: List<SimprintsSearchUtils.SearchField>) {
val searchState = SimprintsSearchUtils.searchState(searchFields)
if (sessionRepository.hasPendingSession() && searchState.shouldClearPendingSession) {
sessionRepository.clear()
}
}

fun shouldUseLastBiometricsLabel(searchFields: List<SimprintsSearchUtils.SearchField>): Boolean {
val searchState = SimprintsSearchUtils.searchState(searchFields)
return SimprintsSearchUtils.shouldUseLastBiometricsLabel(
searchState = searchState,
hasPendingSession = sessionRepository.hasPendingSession(),
)
}


import org.hisp.dhis.android.core.D2

class SimprintsD2Repository(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All of these blocking calls are a bit un-nerving. These are called within withContext(ioDispatcher) in the use cases, which is functional but worth noting under load this could exhaust the IO thread pool.

It also requires that the caller know they are blocking and not call them on the main thread. I know this is a DHIS2 implementation but I wonder if we can wrap our wrapper here with its own context which moves to IO.

import org.dhis2.commons.simprints.repository.SimprintsSessionRepository
import org.dhis2.commons.simprints.usecases.SimprintsResolvePendingEnrollmentActionUseCase

class SimprintsEnrollmentViewModel(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As discussed on slack should extend android VM

import org.dhis2.commons.simprints.usecases.SimprintsResolveConfirmIdentityCalloutUseCase
import org.dhis2.commons.simprints.utils.SimprintsSearchUtils

class SimprintsSearchViewModel(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As discussed on slack should extend android VM

@alex-vt alex-vt merged commit a636a61 into main Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants