Openemr fhir search (#4349)
[openemr.git] / src / Services / FHIR / FhirEncounterService.php
blob39836989ec1fb7d6b14d50ef41c6480ddd607260
1 <?php
3 namespace OpenEMR\Services\FHIR;
5 use OpenEMR\FHIR\Export\ExportCannotEncodeException;
6 use OpenEMR\FHIR\Export\ExportException;
7 use OpenEMR\FHIR\Export\ExportJob;
8 use OpenEMR\FHIR\Export\ExportStreamWriter;
9 use OpenEMR\FHIR\Export\ExportWillShutdownException;
10 use OpenEMR\Services\EncounterService;
11 use OpenEMR\Services\FHIR\FhirServiceBase;
12 use OpenEMR\FHIR\R4\FHIRDomainResource\FHIREncounter;
13 use OpenEMR\FHIR\R4\FHIRElement\FHIRCode;
14 use OpenEMR\FHIR\R4\FHIRElement\FHIRId;
15 use OpenEMR\FHIR\R4\FHIRElement\FHIRCodeableConcept;
16 use OpenEMR\FHIR\R4\FHIRElement\FHIRCoding;
17 use OpenEMR\FHIR\R4\FHIRElement\FHIRPeriod;
18 use OpenEMR\FHIR\R4\FHIRElement\FHIRReference;
19 use OpenEMR\FHIR\R4\FHIRResource\FHIREncounter\FHIREncounterParticipant;
20 use OpenEMR\Services\Search\FhirSearchParameterDefinition;
21 use OpenEMR\Services\Search\SearchFieldType;
22 use OpenEMR\Validators\ProcessingResult;
24 class FhirEncounterService extends FhirServiceBase implements IFhirExportableResourceService
26 /**
27 * @var EncounterService
29 private $encounterService;
31 public function __construct()
33 parent::__construct();
34 $this->encounterService = new EncounterService();
37 /**
38 * Returns an array mapping FHIR Encounter Resource search parameters to OpenEMR Encounter search parameters
39 * @return array The search parameters
41 protected function loadSearchParameters()
43 return [
44 'patient' => new FhirSearchParameterDefinition('patient', SearchFieldType::TOKEN, ['pid']),
45 '_id' => new FhirSearchParameterDefinition('_id', SearchFieldType::TOKEN, ['uuid']),
46 'date' => new FhirSearchParameterDefinition('date', SearchFieldType::DATETIME, ['date'])
50 /**
51 * Parses an OpenEMR patient record, returning the equivalent FHIR Patient Resource
52 * https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-encounter-definitions.html
54 * @param array $dataRecord The source OpenEMR data record
55 * @param boolean $encode Indicates if the returned resource is encoded into a string. Defaults to false.
56 * @return FHIREncounter
58 public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
60 $encounterResource = new FHIREncounter();
62 $meta = array('versionId' => '1', 'lastUpdated' => gmdate('c'));
63 $encounterResource->setMeta($meta);
65 $id = new FhirId();
66 $id->setValue($dataRecord['uuid']);
67 $encounterResource->setId($id);
69 $status = new FHIRCode('finished');
70 $encounterResource->setStatus($status);
72 if (!empty($dataRecord['provider_id'])) {
73 $parctitioner = new FHIRReference(['reference' => 'Practitioner/' . $dataRecord['provider_id']]);
74 $participant = new FHIREncounterParticipant(array(
75 'individual' => $parctitioner,
76 'period' => ['start' => gmdate('c', strtotime($dataRecord['date']))]
77 ));
78 $participantType = new FHIRCodeableConcept();
79 $participantType->addCoding(array(
80 "system" => "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
81 "code" => "PPRF"
82 ));
83 $participantType->setText("Primary Performer");
84 $participant->addType($participantType);
85 $encounterResource->addParticipant($participant);
88 if (!empty($dataRecord['facility_id'])) {
89 $serviceOrg = new FHIRReference(['reference' => 'Organization/' . $dataRecord['facility_id']]);
90 $encounterResource->setServiceProvider($serviceOrg);
93 if (!empty($dataRecord['reason'])) {
94 $reason = new FHIRCodeableConcept();
95 $reason->setText($dataRecord['reason']);
96 $encounterResource->addReasonCode($reason);
99 if (!empty($dataRecord['puuid'])) {
100 $patient = new FHIRReference(['reference' => 'Patient/' . $dataRecord['puuid']]);
101 $encounterResource->setSubject($patient);
104 if (!empty($dataRecord['date'])) {
105 $period = new FHIRPeriod();
106 $period->setStart(gmdate('c', strtotime($dataRecord['date'])));
107 $encounterResource->setPeriod($period);
110 if (!empty($dataRecord['class_code'])) {
111 $class = new FHIRCoding();
112 $class->setSystem("http://terminology.hl7.org/CodeSystem/v3-ActCode");
113 $class->setCode($dataRecord['class_code']);
114 $class->setDisplay($dataRecord['class_title']);
115 $encounterResource->setClass($class);
118 // Encounter.type
119 $type = new FHIRCodeableConcept();
120 $type->addCoding(array(
121 "system" => "http://snomed.info/sct",
122 "code" => "185349003"
124 $type->setText("Encounter for check up (procedure)");
125 $encounterResource->addType($type);
127 if ($encode) {
128 return json_encode($encounterResource);
129 } else {
130 return $encounterResource;
135 * Performs a FHIR Encounter Resource lookup by FHIR Resource ID
136 * @param $fhirResourceId //The OpenEMR record's FHIR Encounter Resource ID.
137 * @param $puuidBind - Optional variable to only allow visibility of the patient with this puuid.
139 public function getOne($fhirResourceId, $puuidBind = null)
141 $processingResult = $this->encounterService->getEncounter($fhirResourceId, $puuidBind);
142 if (!$processingResult->hasErrors()) {
143 if (count($processingResult->getData()) > 0) {
144 $openEmrRecord = $processingResult->getData()[0];
145 $fhirRecord = $this->parseOpenEMRRecord($openEmrRecord);
146 $processingResult->setData([]);
147 $processingResult->addData($fhirRecord);
150 return $processingResult;
154 * Searches for OpenEMR records using OpenEMR search parameters
156 * @param array openEMRSearchParameters OpenEMR search fields
157 * @param $puuidBind - Optional variable to only allow visibility of the patient with this puuid.
158 * @return ProcessingResult
160 public function searchForOpenEMRRecords($searchParam, $puuidBind = null)
162 return $this->encounterService->getEncountersBySearch($searchParam, true, $puuidBind);
165 public function parseFhirResource($fhirResource = array())
167 // TODO: If Required in Future
170 public function insertOpenEMRRecord($openEmrRecord)
172 // TODO: If Required in Future
175 public function updateOpenEMRRecord($fhirResourceId, $updatedOpenEMRRecord)
177 // TODO: If Required in Future
180 public function createProvenanceResource($dataRecord = array(), $encode = false)
182 // TODO: If Required in Future
186 * Grabs all the objects in my service that match the criteria specified in the ExportJob. If a
187 * $lastResourceIdExported is provided, The service executes the same data collection query it used previously and
188 * startes processing at the resource that is immediately after (ordered by date) the resource that matches the id of
189 * $lastResourceIdExported. This allows processing of the service to be resumed or paused.
190 * @param ExportStreamWriter $writer Object that writes out to a stream any object that extend the FhirResource object
191 * @param ExportJob $job The export job we are processing the request for. Holds all of the context information needed for the export service.
192 * @return void
193 * @throws ExportWillShutdownException Thrown if the export is about to be shutdown and all processing must be halted.
194 * @throws ExportException If there is an error in processing the export
195 * @throws ExportCannotEncodeException Thrown if the resource cannot be properly converted into the right format (ie JSON).
197 public function export(ExportStreamWriter $writer, ExportJob $job, $lastResourceIdExported = null): void
199 // TODO: encounter search should support multiple date parameter searches for interval period search
200 // $date = [
201 // 'le' . $job->getStartTime()->format(\DateTime::RFC3339_EXTENDED)
202 // ,'ge' . $job->getResourceIncludeTime()->format(\DateTime::RFC3339_EXTENDED)
203 // ];
204 $date = 'le' . $job->getStartTime()->format(\DateTime::RFC3339_EXTENDED);
205 $result = $this->getAll(['date' => $date]);
206 $encounters = $result->getData();
207 if (!empty($encounters)) {
208 foreach ($encounters as $encounter) {
209 $writer->append($encounter);
215 * Returns whether the service supports the system export operation
216 * @see https://hl7.org/fhir/uv/bulkdata/export/index.html#endpoint---system-level-export
217 * @return bool true if this resource service should be called for a system export operation, false otherwise
219 public function supportsSystemExport()
221 return true;
225 * Returns whether the service supports the group export operation.
226 * Note only resources in the Patient compartment SHOULD be returned unless the resource assists in interpreting
227 * patient data (such as Organization or Practitioner)
228 * @see https://hl7.org/fhir/uv/bulkdata/export/index.html#endpoint---group-of-patients
229 * @return bool true if this resource service should be called for a group export operation, false otherwise
231 public function supportsGroupExport()
233 return true;
237 * Returns whether the service supports the all patient export operation
238 * Note only resources in the Patient compartment SHOULD be returned unless the resource assists in interpreting
239 * patient data (such as Organization or Practitioner)
240 * @see https://hl7.org/fhir/uv/bulkdata/export/index.html#endpoint---all-patients
241 * @return bool true if this resource service should be called for a patient export operation, false otherwise
243 public function supportsPatientExport()
245 return true;