Feat: upgrade e2e testing (#7766)
[openemr.git] / src / Services / FHIR / FhirConditionService.php
blob09e902751d1e6944c52ff718714fc7da3fe29a50
1 <?php
3 namespace OpenEMR\Services\FHIR;
5 use OpenEMR\FHIR\R4\FHIRElement\FHIRCodeableConcept;
6 use OpenEMR\FHIR\R4\FHIRElement\FHIRCoding;
7 use OpenEMR\FHIR\R4\FHIRElement\FHIRId;
8 use OpenEMR\FHIR\R4\FHIRElement\FHIRMeta;
9 use OpenEMR\FHIR\R4\FHIRElement\FHIRReference;
10 use OpenEMR\FHIR\R4\FHIRDomainResource\FHIRCondition;
11 use OpenEMR\Services\FHIR\FhirServiceBase;
12 use OpenEMR\Services\ConditionService;
13 use OpenEMR\Services\FHIR\Traits\BulkExportSupportAllOperationsTrait;
14 use OpenEMR\Services\FHIR\Traits\FhirBulkExportDomainResourceTrait;
15 use OpenEMR\Services\FHIR\Traits\FhirServiceBaseEmptyTrait;
16 use OpenEMR\Services\Search\FhirSearchParameterDefinition;
17 use OpenEMR\Services\Search\ISearchField;
18 use OpenEMR\Services\Search\SearchFieldType;
19 use OpenEMR\Services\Search\ServiceField;
20 use OpenEMR\Validators\ProcessingResult;
22 /**
23 * FHIR Condition Service
25 * @coversDefaultClass OpenEMR\Services\FHIR\FhirConditionService
26 * @package OpenEMR
27 * @link http://www.open-emr.org
28 * @author Yash Bothra <yashrajbothra786gmail.com>
29 * @copyright Copyright (c) 2020 Yash Bothra <yashrajbothra786gmail.com>
30 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
32 class FhirConditionService extends FhirServiceBase implements IResourceUSCIGProfileService, IFhirExportableResourceService, IPatientCompartmentResourceService
34 use FhirServiceBaseEmptyTrait;
35 use BulkExportSupportAllOperationsTrait;
36 use FhirBulkExportDomainResourceTrait;
38 /**
39 * @var ConditionService
41 private $conditionService;
44 const USCGI_PROFILE_URI = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition';
46 public function __construct()
48 parent::__construct();
49 $this->conditionService = new ConditionService();
52 /**
53 * Returns an array mapping FHIR Condition Resource search parameters to OpenEMR Condition search parameters
55 * @return array The search parameters
57 protected function loadSearchParameters()
59 return [
60 'patient' => $this->getPatientContextSearchField(),
61 '_id' => new FhirSearchParameterDefinition('_id', SearchFieldType::TOKEN, [new ServiceField('condition_uuid', ServiceField::TYPE_UUID)]),
62 '_lastUpdated' => $this->getLastModifiedSearchField(),
66 public function getLastModifiedSearchField(): ?FhirSearchParameterDefinition
68 return new FhirSearchParameterDefinition('_lastUpdated', SearchFieldType::DATETIME, ['last_updated_time']);
71 /**
72 * Parses an OpenEMR condition record, returning the equivalent FHIR Condition Resource
74 * @param array $dataRecord The source OpenEMR data record
75 * @param boolean $encode Indicates if the returned resource is encoded into a string. Defaults to false.
76 * @return FHIRCondition
78 public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
80 $conditionResource = new FHIRCondition();
82 $meta = new FHIRMeta();
83 $meta->setVersionId('1');
84 if (!empty($dataRecord['last_updated_time'])) {
85 $meta->setLastUpdated(UtilsService::getLocalDateAsUTC($dataRecord['last_updated_time']));
86 } else {
87 $meta->setLastUpdated(UtilsService::getDateFormattedAsUTC());
89 $conditionResource->setMeta($meta);
91 $id = new FHIRId();
92 $id->setValue($dataRecord['uuid']);
93 $conditionResource->setId($id);
95 // ONC requirements
96 $this->populateClinicalStatus($dataRecord, $conditionResource);
97 $this->populateCategory($dataRecord, $conditionResource);
98 $this->populateVerificationStatus($dataRecord, $conditionResource);
99 $this->populateCode($dataRecord, $conditionResource);
100 $this->populateSubject($dataRecord, $conditionResource);
102 // non-ONC requirements
103 $this->populateEncounter($dataRecord, $conditionResource);
106 if ($encode) {
107 return json_encode($conditionResource);
108 } else {
109 return $conditionResource;
113 private function populateEncounter($dataRecord, FHIRCondition $conditionResource)
115 if (isset($dataRecord['encounter_uuid'])) {
116 $encounter = new FHIRReference();
117 $encounter->setReference('Encounter/' . $dataRecord['encounter_uuid']);
118 $conditionResource->setEncounter($encounter);
122 private function populateSubject($dataRecord, FHIRCondition $conditionResource)
124 if (isset($dataRecord['puuid'])) {
125 $patient = new FHIRReference();
126 $patient->setReference('Patient/' . $dataRecord['puuid']);
127 $conditionResource->setSubject($patient);
131 private function populateCode($dataRecord, FHIRCondition $conditionResource)
133 if (!empty($dataRecord['diagnosis'])) {
134 $diagnosisCoding = new FHIRCoding();
135 $diagnosisCode = new FHIRCodeableConcept();
136 foreach ($dataRecord['diagnosis'] as $code => $codeValues) {
137 if (!is_string($code)) {
138 $code = "$code"; // FHIR expects a string
140 $diagnosisCoding->setCode($code);
141 $diagnosisCoding->setDisplay($codeValues['description']);
142 $diagnosisCoding->setSystem($codeValues['system']);
143 $diagnosisCode->addCoding($diagnosisCoding);
145 $conditionResource->setCode($diagnosisCode);
149 private function populateVerificationStatus($dataRecord, FHIRCondition $conditionResource)
151 $verificationStatus = new FHIRCodeableConcept();
152 $verificationCoding = array(
153 'system' => "http://terminology.hl7.org/CodeSystem/condition-ver-status",
154 'code' => 'unconfirmed',
155 'display' => 'Unconfirmed',
157 if (!empty($dataRecord['verification'])) {
158 $verificationCoding = array(
159 'system' => "http://terminology.hl7.org/CodeSystem/condition-ver-status",
160 'code' => $dataRecord['verification'],
161 'display' => $dataRecord['verification_title']
164 $verificationStatus->addCoding($verificationCoding);
165 $conditionResource->setVerificationStatus($verificationStatus);
168 private function populateCategory($dataRecord, $conditionResource)
171 $conditionCategory = new FHIRCodeableConcept();
172 $conditionCategory->addCoding(
173 array(
174 'system' => "http://terminology.hl7.org/CodeSystem/condition-category",
175 'code' => 'problem-list-item',
176 'display' => 'Problem List Item'
179 $conditionResource->addCategory($conditionCategory);
182 private function populateClinicalStatus($dataRecord, FHIRCondition $conditionResource)
184 $clinicalStatus = "inactive";
185 $clinicalSysytem = "http://terminology.hl7.org/CodeSystem/condition-clinical";
186 if (
187 (!isset($dataRecord['enddate']) && isset($dataRecord['begdate']))
188 || isset($dataRecord['enddate']) && strtotime($dataRecord['enddate']) >= strtotime("now")
190 // Active if Only Begin Date isset OR End Date isnot expired
191 $clinicalStatus = "active";
192 if ($dataRecord['occurrence'] == 1 || $dataRecord['outcome'] == 1) {
193 $clinicalStatus = "resolved";
194 } elseif ($dataRecord['occurrence'] > 1) {
195 $clinicalStatus = "recurrence";
197 } elseif (isset($dataRecord['enddate']) && strtotime($dataRecord['enddate']) < strtotime("now")) {
198 //Inactive if End Date is expired
199 $clinicalStatus = "inactive";
200 } else {
201 $clinicalSysytem = "http://terminology.hl7.org/CodeSystem/data-absent-reason";
202 $clinicalStatus = "unknown";
204 $clinical_Status = new FHIRCodeableConcept();
205 $clinical_Status->addCoding(
206 array(
207 'system' => $clinicalSysytem,
208 'code' => $clinicalStatus,
209 'display' => ucwords($clinicalStatus),
212 $conditionResource->setClinicalStatus($clinical_Status);
216 * Searches for OpenEMR records using OpenEMR search parameters
218 * @param array openEMRSearchParameters OpenEMR search fields
219 * @param $puuidBind - Optional variable to only allow visibility of the patient with this puuid.
220 * @return ProcessingResult
222 protected function searchForOpenEMRRecords($openEMRSearchParameters, $puuidBind = null): ProcessingResult
224 $result = $this->conditionService->getAll($openEMRSearchParameters, true, $puuidBind);
225 return $result;
228 public function createProvenanceResource($dataRecord = array(), $encode = false)
230 if (!($dataRecord instanceof FHIRCondition)) {
231 throw new \BadMethodCallException("Data record should be correct instance class");
233 $fhirProvenanceService = new FhirProvenanceService();
234 $fhirProvenance = $fhirProvenanceService->createProvenanceForDomainResource($dataRecord);
235 if ($encode) {
236 return json_encode($fhirProvenance);
237 } else {
238 return $fhirProvenance;
243 * Returns the Canonical URIs for the FHIR resource for each of the US Core Implementation Guide Profiles that the
244 * resource implements. Most resources have only one profile, but several like DiagnosticReport and Observation
245 * has multiple profiles that must be conformed to.
246 * @see https://www.hl7.org/fhir/us/core/CapabilityStatement-us-core-server.html for the list of profiles
247 * @return string[]
249 function getProfileURIs(): array
251 return [self::USCGI_PROFILE_URI];
254 public function getPatientContextSearchField(): FhirSearchParameterDefinition
256 return new FhirSearchParameterDefinition('patient', SearchFieldType::REFERENCE, [new ServiceField('puuid', ServiceField::TYPE_UUID)]);