Skip to content

Commit

Permalink
Fetch and save logged in practitioner details (#1296)
Browse files Browse the repository at this point in the history
* Fetch and save logged in practitioner details

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>

* Resolve questionnaire subject reference

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>

* Decrypt database on debug mode

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>

* Fix tests failing silently

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>

* Test LoginViewModel#fetchLoggedInPractitioner

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>

* Test setting organization reference

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>

* Make loginErrorState parameter of LoginScreenKt#LoginPage nullable

Signed-off-by: Elly Kitoto <junkmailstoelly@gmail.com>
  • Loading branch information
ellykits authored May 23, 2022
1 parent 219659e commit c56721a
Show file tree
Hide file tree
Showing 30 changed files with 495 additions and 268 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ class BmiQuestionnaireActivity : QuestionnaireActivity() {
questionnaireViewModel.extractAndSaveResources(
this@BmiQuestionnaireActivity,
patientId,
questionnaire,
questionnaireResponse
intent.getStringExtra(QUESTIONNAIRE_ARG_GROUP_KEY),
questionnaireResponse,
questionnaire = questionnaire
)
exitForm()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ class FamilyQuestionnaireActivity : QuestionnaireActivity() {
saveBtn.hide(false)

questionnaireViewModel.extractAndSaveResources(
this,
intent.getStringExtra(QUESTIONNAIRE_ARG_PATIENT_KEY),
questionnaire,
questionnaireResponse,
questionnaireType
context = this,
resourceId = intent.getStringExtra(QUESTIONNAIRE_ARG_PATIENT_KEY),
groupResourceId = intent.getStringExtra(QUESTIONNAIRE_ARG_GROUP_KEY),
questionnaireResponse = questionnaireResponse,
questionnaireType = questionnaireType,
questionnaire = questionnaire
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.hl7.fhir.r4.model.MeasureReport
import org.hl7.fhir.r4.model.Practitioner
import org.smartregister.fhircore.anc.data.model.PatientItem
import org.smartregister.fhircore.anc.data.patient.PatientRepository
import org.smartregister.fhircore.anc.data.report.ReportRepository
Expand All @@ -49,14 +50,12 @@ import org.smartregister.fhircore.anc.data.report.model.ResultItem
import org.smartregister.fhircore.anc.data.report.model.ResultItemPopulation
import org.smartregister.fhircore.anc.ui.anccare.register.AncRowClickListenerIntent
import org.smartregister.fhircore.anc.ui.anccare.register.OpenPatientProfile
import org.smartregister.fhircore.engine.data.remote.model.response.UserInfo
import org.smartregister.fhircore.engine.domain.util.PaginationConstant
import org.smartregister.fhircore.engine.ui.register.model.RegisterFilterType
import org.smartregister.fhircore.engine.util.DispatcherProvider
import org.smartregister.fhircore.engine.util.LOGGED_IN_PRACTITIONER
import org.smartregister.fhircore.engine.util.ListenerIntent
import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
import org.smartregister.fhircore.engine.util.USER_INFO_SHARED_PREFERENCE_KEY
import org.smartregister.fhircore.engine.util.extension.decodeJson
import org.smartregister.fhircore.engine.util.extension.loadCqlLibraryBundle

@HiltViewModel
Expand Down Expand Up @@ -102,10 +101,6 @@ constructor(
private val measureReportDateFormatter =
SimpleDateFormat(MEASURE_REPORT_DATE_FORMAT, Locale.getDefault())

private val authenticatedUserInfo by lazy {
sharedPreferencesHelper.read(USER_INFO_SHARED_PREFERENCE_KEY, null)?.decodeJson<UserInfo>()
}

private val _dateRange =
MutableLiveData(
androidx.core.util.Pair(
Expand Down Expand Up @@ -198,6 +193,11 @@ constructor(
)
}

val loggedInPractitioner =
sharedPreferencesHelper.read<Practitioner>(
key = LOGGED_IN_PRACTITIONER,
decodeFhirResource = true
)
if (selectedPatientItem.value != null && individualEvaluation) {
val measureReport =
withContext(dispatcher.io()) {
Expand All @@ -207,8 +207,8 @@ constructor(
end = endDateFormatted,
reportType = SUBJECT,
subject = selectedPatientItem.value!!.patientIdentifier,
practitioner = authenticatedUserInfo?.keyclockuuid!!,
lastReceivedOn = null // Non-null value not supported yet
practitioner = loggedInPractitioner?.id,
lastReceivedOn = null
)
}

Expand All @@ -230,7 +230,7 @@ constructor(
end = endDateFormatted,
reportType = POPULATION,
subject = null,
practitioner = authenticatedUserInfo?.keyclockuuid!!,
practitioner = loggedInPractitioner?.id,
lastReceivedOn = null // Non-null value not supported yet
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ object FakeModel {
UserInfo().apply {
questionnairePublisher = "ab"
organization = "1111"
keyclockuuid = "123"
keycloakUuid = "123"
}
return userInfo
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.OperationOutcome
import org.hl7.fhir.r4.model.Resource

/** Implementation of the [DataSource] that communicates with hapi fhir. */
/** Interact with HAPI FHIR server */
class FhirResourceDataSource @Inject constructor(private val resourceService: FhirResourceService) {

suspend fun loadData(path: String): Bundle {
Expand All @@ -49,4 +49,7 @@ class FhirResourceDataSource @Inject constructor(private val resourceService: Fh
suspend fun delete(resourceType: String, resourceId: String): OperationOutcome {
return resourceService.deleteResource(resourceType, resourceId)
}

suspend fun search(resourceType: String, searchParameters: Map<String, String>): Bundle =
resourceService.searchResource(resourceType, searchParameters)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,39 @@ import retrofit2.http.GET
import retrofit2.http.PATCH
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.QueryMap
import retrofit2.http.Url

/** [Retrofit] Service for communication with HAPI FHIR server. Used for querying FHIR Resources */
interface FhirResourceService {

@GET suspend fun getResource(@Url url: String): Bundle
@PUT("{type}/{id}")

@PUT("{resourceType}/{id}")
suspend fun insertResource(
@Path("type") type: String,
@Path("resourceType") resourceType: String,
@Path("id") id: String,
@Body body: RequestBody
): Resource
@PATCH("{type}/{id}")

@PATCH("{resourceType}/{id}")
suspend fun updateResource(
@Path("type") type: String,
@Path("resourceType") resourceType: String,
@Path("id") id: String,
@Body body: RequestBody
): OperationOutcome
@DELETE("{type}/{id}")
suspend fun deleteResource(@Path("type") type: String, @Path("id") id: String): OperationOutcome

@DELETE("{resourceType}/{id}")
suspend fun deleteResource(
@Path("resourceType") resourceType: String,
@Path("id") id: String
): OperationOutcome

@GET fun fetchImage(@Url url: String): Call<ResponseBody?>

@GET("{resourceType}/_search")
suspend fun searchResource(
@Path("resourceType") resourceType: String,
@QueryMap(encoded = false) searchParameters: Map<String, String>
): Bundle
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ data class UserInfo(
@SerialName("questionnaire_publisher") var questionnairePublisher: String? = null,
@SerialName("organization") var organization: String? = null,
@SerialName("location") var location: String? = null,
@SerialName("sub") var keyclockuuid: String? = null
@SerialName("sub") var keycloakUuid: String? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.smartregister.fhircore.engine.BuildConfig
import org.smartregister.fhircore.engine.auth.TokenManagerService
import org.smartregister.fhircore.engine.configuration.app.ConfigService

Expand All @@ -48,7 +49,7 @@ class FhirEngineModule {
): FhirEngine {
FhirEngineProvider.init(
FhirEngineConfiguration(
enableEncryptionIfSupported = true,
enableEncryptionIfSupported = !BuildConfig.DEBUG,
DatabaseErrorStrategy.UNSPECIFIED,
ServerConfiguration(
baseUrl = configService.provideAuthConfiguration().fhirServerBaseUrl,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.engine.ui.login

enum class LoginErrorState {
UNKNOWN_HOST,
INVALID_CREDENTIALS
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fun LoginScreen(loginViewModel: LoginViewModel) {
)
val username by loginViewModel.username.observeAsState("")
val password by loginViewModel.password.observeAsState("")
val loginError by loginViewModel.loginError.observeAsState("")
val loginErrorState by loginViewModel.loginErrorState.observeAsState(null)
val showProgressBar by loginViewModel.showProgressBar.observeAsState(false)

LoginPage(
Expand All @@ -109,7 +109,7 @@ fun LoginScreen(loginViewModel: LoginViewModel) {
onPasswordChanged = { loginViewModel.onPasswordUpdated(it) },
forgotPassword = { loginViewModel.forgotPassword() },
onLoginButtonClicked = { loginViewModel.attemptRemoteLogin() },
loginError = loginError,
loginErrorState = loginErrorState,
showProgressBar = showProgressBar,
)
}
Expand All @@ -124,7 +124,7 @@ fun LoginPage(
forgotPassword: () -> Unit,
onLoginButtonClicked: () -> Unit,
modifier: Modifier = Modifier,
loginError: String = "",
loginErrorState: LoginErrorState? = null,
showProgressBar: Boolean = false,
) {
var showPassword by remember { mutableStateOf(false) }
Expand Down Expand Up @@ -181,7 +181,7 @@ fun LoginPage(
.align(Alignment.CenterHorizontally)
.testTag(APP_NAME_TEXT_TAG)
)
Spacer(modifier = modifier.height(60.dp))
Spacer(modifier = modifier.height(40.dp))
Text(
text = stringResource(R.string.username),
color = contentColor,
Expand Down Expand Up @@ -251,20 +251,31 @@ fun LoginPage(
}
)
Spacer(modifier = modifier.height(10.dp))
if (loginError.isNotEmpty()) {
Text(
fontSize = 14.sp,
color = MaterialTheme.colors.error,
text = stringResource(id = R.string.login_error, loginError),
modifier =
modifier
.wrapContentWidth()
.padding(0.dp)
.align(Alignment.Start)
.testTag(LOGIN_ERROR_TEXT_TAG)
)
}
Spacer(modifier = modifier.height(40.dp))
Text(
fontSize = 14.sp,
color = MaterialTheme.colors.error,
text =
when (loginErrorState) {
LoginErrorState.UNKNOWN_HOST ->
stringResource(
id = R.string.login_error,
stringResource(R.string.login_call_fail_error_message)
)
LoginErrorState.INVALID_CREDENTIALS ->
stringResource(
id = R.string.login_error,
stringResource(R.string.invalid_login_credentials)
)
null -> ""
},
modifier =
modifier
.wrapContentWidth()
.padding(0.dp)
.align(Alignment.Start)
.testTag(LOGIN_ERROR_TEXT_TAG)
)
Spacer(modifier = modifier.height(30.dp))
Box(contentAlignment = Alignment.Center, modifier = modifier.fillMaxWidth()) {
Button(
enabled = !showProgressBar && username.isNotEmpty() && password.isNotEmpty(),
Expand Down
Loading

0 comments on commit c56721a

Please sign in to comment.