Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit dd4379d

Browse files
authoredMay 4, 2022
add referring provider to FhirEncounterService (openemr#5281)
* add referring provider to FhirEncounterService * typo
1 parent 871ae51 commit dd4379d

File tree

5 files changed

+254
-28
lines changed

5 files changed

+254
-28
lines changed
 

‎src/RestControllers/AuthorizationController.php

+10-7
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ class AuthorizationController
7676
{
7777
use CryptTrait;
7878

79-
const ENDPOINT_SCOPE_AUTHORIZE_CONFIRM = "/scope-authorize-confirm";
79+
public const ENDPOINT_SCOPE_AUTHORIZE_CONFIRM = "/scope-authorize-confirm";
8080

81-
const GRANT_TYPE_PASSWORD = 'password';
82-
const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials';
83-
const OFFLINE_ACCESS_SCOPE = 'offline_access';
81+
public const GRANT_TYPE_PASSWORD = 'password';
82+
public const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials';
83+
public const OFFLINE_ACCESS_SCOPE = 'offline_access';
8484

8585
public $authBaseUrl;
8686
public $authBaseFullUrl;
@@ -157,7 +157,10 @@ private function configKeyPairs(): void
157157
$this->passphrase = $oauth2KeyConfig->getPassPhrase();
158158
} catch (OAuth2KeyException $exception) {
159159
$this->logger->error("OpenEMR error - " . $exception->getMessage() . ", so forced exit");
160-
$serverException = OAuthServerException::serverError("Security error - problem with authorization server keys.", $exception);
160+
$serverException = OAuthServerException::serverError(
161+
"Security error - problem with authorization server keys.",
162+
$exception
163+
);
161164
SessionUtil::oauthSessionCookieDestroy();
162165
$this->emitResponse($serverException->generateHttpResponse($response));
163166
exit;
@@ -237,7 +240,7 @@ public function clientRegistration(): void
237240
throw new OAuthServerException('jwks is invalid', 0, 'invalid_client_metadata');
238241
}
239242
// don't allow user, system scopes, and offline_access for public apps
240-
} else if (
243+
} elseif (
241244
strpos($data['scope'], 'system/') !== false
242245
|| strpos($data['scope'], 'user/') !== false
243246
|| strpos($data['scope'], self::OFFLINE_ACCESS_SCOPE) !== false
@@ -512,7 +515,7 @@ public function oauthAuthorizationFlow(): void
512515
$response = $this->createServerResponse();
513516
$request = $this->createServerRequest();
514517

515-
if ($nonce = $request->getQueryParams()['nonce']) {
518+
if ($nonce = $request->getQueryParams()['nonce'] ?? null) {
516519
$_SESSION['nonce'] = $request->getQueryParams()['nonce'];
517520
}
518521

‎src/Services/EncounterService.php

+17-3
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public function getOneByPidEid($pid, $encounter_id)
107107
public function getUuidFields(): array
108108
{
109109
return ['provider_uuid', 'facility_uuid', 'euuid', 'puuid', 'billing_facility_uuid'
110-
, 'facility_location_uuid', 'billing_location_uuid'];
110+
, 'facility_location_uuid', 'billing_location_uuid', 'referrer_uuid'];
111111
}
112112

113113
/**
@@ -210,8 +210,11 @@ class.notes as class_title,
210210
fa.billing_location_uuid,
211211
212212
fe.provider_id,
213+
fe.referring_provider_id,
213214
providers.provider_uuid,
214215
providers.provider_username,
216+
referrers.referrer_uuid,
217+
referrers.referrer_username,
215218
fe.discharge_disposition,
216219
discharge_list.discharge_disposition_text
217220
@@ -240,7 +243,8 @@ class.notes as class_title,
240243
class_code,
241244
facility_id,
242245
discharge_disposition,
243-
pid as encounter_pid
246+
pid as encounter_pid,
247+
referring_provider_id
244248
FROM form_encounter
245249
) fe
246250
LEFT JOIN openemr_postcalendar_categories as opc
@@ -271,6 +275,15 @@ class_code,
271275
WHERE
272276
npi IS NOT NULL and npi != ''
273277
) providers ON fe.provider_id = providers.provider_provider_id
278+
LEFT JOIN (
279+
select
280+
id AS referring_provider_id
281+
,uuid AS referrer_uuid
282+
,`username` AS referrer_username
283+
FROM users
284+
WHERE
285+
npi IS NOT NULL and npi != ''
286+
) referrers ON fe.referring_provider_id = referrers.referring_provider_id
274287
LEFT JOIN (
275288
select
276289
facility.id AS facility_id
@@ -367,7 +380,8 @@ public function insertEncounter($puuid, $data)
367380
$data["provider_id"],
368381
$data["date"],
369382
$data['user'],
370-
$data['group']
383+
$data['group'],
384+
$data['referring_provider_id']
371385
);
372386

373387
if ($results) {

‎src/Services/FHIR/FhirEncounterService.php

+97-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
<?php
22

3+
/**
4+
* FhirEncounterService
5+
*
6+
* @package OpenEMR
7+
* @link http://www.open-emr.org
8+
* @author Yash Bothra <yashrajbothra786@gmail.com>
9+
* @author Stephen Waite <stephen.waite@cmsvt.com>
10+
* @author Vishnu Yarmaneni <vardhanvishnu@gmail.com>
11+
* @author Brady Miller <brady.g.miller@gmail.com>
12+
* @author Stephen Nielson snielson@discoverandchange.com
13+
* @copyright Copyright (c) 2020 Yash Bothra <yashrajbothra786@gmail.com>
14+
* @copyright Copyright (c) 2020, 2022 Stephen Waite <stephen.waite@cmsvt.com>
15+
* @copyright Copyright (c) 2020 Vishnu Yarmaneni <vardhanvishnu@gmail.com>
16+
* @copyright Copyright (c) 2021 Brady Miller <brady.g.miller@gmail.com>
17+
* @copyright Copyright (c) 2022 Stephen Nielson <snielson@discoverandchange.com>
18+
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
19+
*/
20+
321
namespace OpenEMR\Services\FHIR;
422

523
use DateTime;
@@ -25,20 +43,26 @@
2543
use OpenEMR\Services\Search\ServiceField;
2644
use OpenEMR\Validators\ProcessingResult;
2745

28-
class FhirEncounterService extends FhirServiceBase implements IFhirExportableResourceService, IPatientCompartmentResourceService, IResourceUSCIGProfileService
46+
class FhirEncounterService extends FhirServiceBase implements
47+
IFhirExportableResourceService,
48+
IPatientCompartmentResourceService,
49+
IResourceUSCIGProfileService
2950
{
3051
use PatientSearchTrait;
3152
use FhirServiceBaseEmptyTrait;
3253
use BulkExportSupportAllOperationsTrait;
3354
use FhirBulkExportDomainResourceTrait;
3455

35-
const ENCOUNTER_STATUS_FINISHED = "finished";
56+
public const ENCOUNTER_STATUS_FINISHED = "finished";
57+
58+
public const ENCOUNTER_TYPE_CHECK_UP = "185349003";
59+
public const ENCOUNTER_TYPE_CHECK_UP_DESCRIPTION = "Encounter for check up (procedure)";
3660

37-
const ENCOUNTER_TYPE_CHECK_UP = "185349003";
38-
const ENCOUNTER_TYPE_CHECK_UP_DESCRIPTION = "Encounter for check up (procedure)";
61+
public const ENCOUNTER_PARTICIPANT_TYPE_PRIMARY_PERFORMER = "PPRF";
62+
public const ENCOUNTER_PARTICIPANT_TYPE_PRIMARY_PERFORMER_TEXT = "Primary Performer";
3963

40-
const ENCOUNTER_PARTICIPANT_TYPE_PRIMARY_PERFORMER = "PPRF";
41-
const ENCOUNTER_PARTICIPANT_TYPE_PRIMARY_PERFORMER_TEXT = "Primary Performer";
64+
public const ENCOUNTER_PARTICIPANT_TYPE_REFERRER = "REF";
65+
public const ENCOUNTER_PARTICIPANT_TYPE_REFERRER_TEXT = "Referrer";
4266

4367

4468
/**
@@ -59,7 +83,16 @@ public function __construct()
5983
protected function loadSearchParameters()
6084
{
6185
return [
62-
'_id' => new FhirSearchParameterDefinition('_id', SearchFieldType::TOKEN, [new ServiceField('euuid', ServiceField::TYPE_UUID)]),
86+
'_id' => new FhirSearchParameterDefinition(
87+
'_id',
88+
SearchFieldType::TOKEN,
89+
[
90+
new ServiceField(
91+
'euuid',
92+
ServiceField::TYPE_UUID
93+
)
94+
]
95+
),
6396
'patient' => $this->getPatientContextSearchField(),
6497
'date' => new FhirSearchParameterDefinition('date', SearchFieldType::DATETIME, ['date'])
6598
];
@@ -107,7 +140,8 @@ public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
107140
$encounterResource->setClass(UtilsService::createDataAbsentUnknownCodeableConcept());
108141
}
109142

110-
// TODO: @adunsulag check with @brady.miller and find out if this really is the only possible encounter type... it was here originally
143+
// TODO: @adunsulag check with @brady.miller and find out if this really is the only possible encounter type
144+
// ... it was here originally
111145
$type = UtilsService::createCodeableConcept(
112146
[self::ENCOUNTER_TYPE_CHECK_UP => [
113147
'code' => self::ENCOUNTER_TYPE_CHECK_UP
@@ -127,7 +161,12 @@ public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
127161
// participant - must support
128162
if (!empty($dataRecord['provider_uuid'])) {
129163
$participant = new FHIREncounterParticipant();
130-
$participant->setIndividual(UtilsService::createRelativeReference("Practitioner", $dataRecord['provider_uuid']));
164+
$participant->setIndividual(
165+
UtilsService::createRelativeReference(
166+
"Practitioner",
167+
$dataRecord['provider_uuid']
168+
)
169+
);
131170
$period = new FHIRPeriod();
132171
$period->setStart(DateTime::createFromFormat("Y-m-d H:i:s", $dataRecord['date'])->format('c'));
133172
$period->setStart(gmdate('c', strtotime($dataRecord['date'])));
@@ -145,6 +184,32 @@ public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
145184
$encounterResource->addParticipant($participant);
146185
}
147186

187+
// referring provider
188+
if (!empty($dataRecord['referrer_uuid'])) {
189+
$participant = new FHIREncounterParticipant();
190+
$participant->setIndividual(
191+
UtilsService::createRelativeReference(
192+
"Practitioner",
193+
$dataRecord['referrer_uuid']
194+
)
195+
);
196+
$period = new FHIRPeriod();
197+
$period->setStart(DateTime::createFromFormat("Y-m-d H:i:s", $dataRecord['date'])->format('c'));
198+
$period->setStart(gmdate('c', strtotime($dataRecord['date'])));
199+
$participant->setPeriod($period);
200+
201+
$participantType = UtilsService::createCodeableConcept([
202+
self::ENCOUNTER_PARTICIPANT_TYPE_REFERRER =>
203+
[
204+
'code' => self::ENCOUNTER_PARTICIPANT_TYPE_REFERRER
205+
,'description' => self::ENCOUNTER_PARTICIPANT_TYPE_REFERRER_TEXT
206+
,'system' => FhirCodeSystemConstants::HL7_PARTICIPATION_TYPE
207+
]
208+
]);
209+
$participant->addType($participantType);
210+
$encounterResource->addParticipant($participant);
211+
}
212+
148213
// period - must support
149214
if (!empty($dataRecord['date'])) {
150215
$period = new FHIRPeriod();
@@ -155,9 +220,10 @@ public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
155220
// reasonCode - must support OR must support reasonReference
156221
if (!empty($dataRecord['reason'])) {
157222
// Note: that we use the encounter textual representation for the reason here which is just fine as ccda
158-
// uses a textual representation of this. According to HL7 chat this is just fine as epoch and other systems
159-
// do it this way
160-
// @see https://chat.fhir.org/#narrow/stream/179175-argonaut/topic/Encounter.20Reason.20For.20Visit (beware of link rot)
223+
// uses a textual representation of this. According to HL7 chat this is just fine as epoch and
224+
// other systems do it this way
225+
// @see https://chat.fhir.org/#narrow/stream/179175-argonaut/topic/Encounter.20Reason.20For.20Visit
226+
// (beware of link rot)
161227
$reason = new FHIRCodeableConcept();
162228
$reasonText = $dataRecord['reason'] ?? "";
163229
$reason->setText(trim($reasonText));
@@ -172,7 +238,13 @@ public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
172238

173239
$hospitalization = new FHIREncounterHospitalization();
174240
$hospitalization->setDischargeDisposition(UtilsService::createCodeableConcept(
175-
[$code => ['code' => $text, 'description' => $text, 'system' => FhirCodeSystemConstants::HL7_DISCHARGE_DISPOSITION]]
241+
[
242+
$code => [
243+
'code' => $text,
244+
'description' => $text,
245+
'system' => FhirCodeSystemConstants::HL7_DISCHARGE_DISPOSITION
246+
]
247+
]
176248
));
177249
$encounterResource->setHospitalization($hospitalization);
178250
}
@@ -182,12 +254,22 @@ public function parseOpenEMRRecord($dataRecord = array(), $encode = false)
182254
// location.location - must support
183255
// serviceProvider - must support
184256
if (!empty($dataRecord['facility_uuid'])) {
185-
$encounterResource->setServiceProvider(UtilsService::createRelativeReference('Organization', $dataRecord['facility_uuid']));
257+
$encounterResource->setServiceProvider(
258+
UtilsService::createRelativeReference(
259+
'Organization',
260+
$dataRecord['facility_uuid']
261+
)
262+
);
186263

187264
// grab the facility location address
188265
if (!empty($dataRecord['facility_location_uuid'])) {
189266
$location = new FHIREncounterLocation();
190-
$location->setLocation(UtilsService::createRelativeReference("Location", $dataRecord['facility_location_uuid']));
267+
$location->setLocation(
268+
UtilsService::createRelativeReference(
269+
"Location",
270+
$dataRecord['facility_location_uuid']
271+
)
272+
);
191273
$encounterResource->addLocation($location);
192274
}
193275
}

‎tests/api/InternalApiTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
// (when done, remember to uncomment it again)
1515
exit;
1616

17-
1817
require_once(__DIR__ . "/../../interface/globals.php");
1918

2019
use OpenEMR\Common\Csrf\CsrfUtils;
@@ -87,14 +86,15 @@ function testFetchApi() {
8786
// CALL the api via route handler
8887
// This allows same notation as the calls in the api (ie. '/api/facility'), but
8988
// is limited to get requests at this time.
89+
use OpenEMR\Common\Http\HttpRestRequest;
9090
use OpenEMR\Common\Http\HttpRestRouteHandler;
9191

9292
require_once(__DIR__ . "/../../_rest_config.php");
9393
$gbl = RestConfig::GetInstance();
9494
$gbl::setNotRestCall();
95-
$restRequest = new HttpRestRouteHandler($gbl, $_SERVER);
95+
$restRequest = new HttpRestRequest($gbl, $_SERVER);
9696
$restRequest->setRequestMethod("GET");
97-
$restRequest->setRequestResource("/api/facility");
97+
$restRequest->setRequestURI("/api/facility");
9898
// below will return as json
9999
echo "<b>api via route handler call returning json:</b><br />";
100100
echo HttpRestRouteHandler::dispatch($gbl::$ROUTE_MAP, $restRequest, 'direct-json');
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.