diff --git a/workflow/src/main/java/com/google/android/fhir/workflow/activity/ActivityFlow.kt b/workflow/src/main/java/com/google/android/fhir/workflow/activity/ActivityFlow.kt index ede47ac171..3ccc1664d3 100644 --- a/workflow/src/main/java/com/google/android/fhir/workflow/activity/ActivityFlow.kt +++ b/workflow/src/main/java/com/google/android/fhir/workflow/activity/ActivityFlow.kt @@ -17,6 +17,8 @@ package com.google.android.fhir.workflow.activity import androidx.annotation.WorkerThread +import ca.uhn.fhir.model.api.IQueryParameterType +import ca.uhn.fhir.rest.param.ReferenceParam import com.google.android.fhir.workflow.activity.phase.Phase import com.google.android.fhir.workflow.activity.phase.Phase.PhaseName import com.google.android.fhir.workflow.activity.phase.Phase.PhaseName.ORDER @@ -34,6 +36,11 @@ import com.google.android.fhir.workflow.activity.resource.request.CPGCommunicati import com.google.android.fhir.workflow.activity.resource.request.CPGMedicationRequest import com.google.android.fhir.workflow.activity.resource.request.CPGRequestResource import com.google.android.fhir.workflow.activity.resource.request.Intent +import org.hl7.fhir.r4.model.Bundle +import org.hl7.fhir.r4.model.CommunicationRequest +import org.hl7.fhir.r4.model.MedicationRequest +import org.hl7.fhir.r4.model.ServiceRequest +import org.hl7.fhir.r4.model.Task import org.opencds.cqf.fhir.api.Repository /** @@ -303,5 +310,107 @@ private constructor( resource: CPGOrderMedicationEvent<*>, ): ActivityFlow> = ActivityFlow(repository, null, resource) + + /** + * This returns a list of flows and because of type erasure, its not possible to do a + * filterInstance with specific CPG resource types. Instead, use list.filter and check the cpg + * type of the [ActivityFlow.requestResource] instead. + */ + fun of( + repository: Repository, + patientId: String, + ): List, CPGEventResource<*>>> { + val tasks = + repository + .search( + Bundle::class.java, + Task::class.java, + mutableMapOf>( + Task.SUBJECT.paramName to mutableListOf(ReferenceParam("Patient/$patientId")), + ), + null, + ) + .entry + .map { it.resource } + val medicationRequests = + repository + .search( + Bundle::class.java, + MedicationRequest::class.java, + mutableMapOf>( + MedicationRequest.SUBJECT.paramName to + mutableListOf(ReferenceParam("Patient/$patientId")), + ), + null, + ) + .entry + .map { it.resource } + val communicationRequests = + repository + .search( + Bundle::class.java, + CommunicationRequest::class.java, + mutableMapOf>( + CommunicationRequest.SUBJECT.paramName to + mutableListOf(ReferenceParam("Patient/$patientId")), + ), + null, + ) + .entry + .map { it.resource } + + val serviceRequests = + repository + .search( + Bundle::class.java, + ServiceRequest::class.java, + mutableMapOf>( + ServiceRequest.SUBJECT.paramName to + mutableListOf(ReferenceParam("Patient/$patientId")), + ), + null, + ) + .entry + .map { it.resource } + + val cache: MutableMap> = + sequenceOf(tasks, communicationRequests, serviceRequests, medicationRequests) + .flatten() + .map { CPGRequestResource.of(it) } + .associateByTo(LinkedHashMap()) { "${it.resourceType}/${it.logicalId}" } + fun addBasedOn( + request: RequestChain>, + ): RequestChain>? { + request.request.getBasedOn()?.let { reference -> + cache[reference.reference]?.let { + cache.remove(reference.reference) + request.basedOn = RequestChain(it, addBasedOn(RequestChain(it, null))) + request.basedOn + } + } + return null + } + val requestChain = + cache.values + .filter { + it.getIntent() == Intent.ORDER || + it.getIntent() == Intent.PLAN || + it.getIntent() == Intent.PROPOSAL + } + .sortedByDescending { it.getIntent().code } + .mapNotNull { + if (cache.containsKey("${it.resourceType}/${it.logicalId}")) { + RequestChain(it, addBasedOn(RequestChain(it, null))) + } else { + null + } + } + return requestChain.map { ActivityFlow(repository, it.request) } + } } } + +internal data class RequestChain>( + val request: CPGRequestResource<*>, + var basedOn: RequestChain?, +)