4 * interface/eRxSOAP.php Functions for interacting with NewCrop SOAP calls.
6 * Copyright (C) 2013 Sam Likins <sam.likins@wsi-services.com>
8 * LICENSE: This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at your option) any
11 * later version. This program is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 * Public License for more details. You should have received a copy of the GNU
15 * General Public License along with this program.
16 * If not, see <http://opensource.org/licenses/gpl-license.php>.
20 * @author Sam Likins <sam.likins@wsi-services.com>
21 * @link http://www.open-emr.org
24 require_once($GLOBALS['fileroot'] . '/interface/eRxStore.php');
25 require_once($GLOBALS['srcdir'] . '/xmltoarray_parser_htmlfix.php');
26 require_once($GLOBALS['srcdir'] . '/lists.inc');
27 require_once($GLOBALS['srcdir'] . '/amc.php');
31 const ACTION_ALLERGIES
= 'allergies';
32 const ACTION_MEDICATIONS
= 'medications';
34 const FLAG_PRESCRIPTION_PRESS
= '1';
35 const FLAG_PRESCRIPTION_IMPORT
= '2';
36 const FLAG_ALLERGY_PRESS
= '3';
37 const FLAG_ALLERGY_IMPORT
= '4';
41 private $authUserDetails;
46 private $soapSettings = array();
51 * Repair HTML/XML and return array
52 * @param string $xml XML for processing
53 * @return array|boolean Array on success, false on failure
55 static public function htmlFixXmlToArray($xml) {
56 $xmltoarray = new xmltoarray_parser_htmlfix(); //create instance of class
58 $xmltoarray->xmlparser_setoption(XML_OPTION_SKIP_WHITE
, 1); //set options same as xml_parser_set_option
59 $xmltoarray->xmlparser_setoption(XML_OPTION_CASE_FOLDING
, 0);
61 $xmltoarray->xmlparser_fix_into_struct(base64_decode($xml)); //fixes html values for XML
63 $array = $xmltoarray->createArray(); //creates an array with fixed html values
65 foreach($array as $key => $value) {
66 $array[$key] = $xmltoarray->fix_html_entities($value); //returns proper html values
69 if(array_key_exists('NewDataSet', $array) && array_key_exists('Table', $array['NewDataSet']))
70 $array = $array['NewDataSet']['Table'];
78 * Set Store to handle eRx cashed data
79 * @param object $store The eRx Store object to use for processing
80 * @return eRxSOAP This object is returned for method chaining
82 public function setStore($store) {
83 $this->store
= $store;
89 * Get Store for handling eRx cashed data
90 * @return object The eRx Store object to use for processing
92 public function getStore() {
97 * Set Account Id for SOAP communications with NewCrop
98 * @param string $id The Account Id to send with SOAP requests to NewCrop
99 * @return eRxSOAP This object is returned for method chaining
101 public function setAccountId($id) {
102 $this->accountId
= $id;
108 * Get Account Id set for SOAP communications with NewCrop
109 * @return string The Account Id sent with SOAP requests to NewCrop
111 public function getAccountId() {
112 if(null === $this->accountId
)
113 $this->accountId
= $GLOBALS['erx_account_id'];
115 return $this->accountId
;
119 * Set SiteId for SOAP communications with NewCrop
120 * @param string $id The Site Id to send with SOAP requests to NewCrop
121 * @return eRxSOAP This object is returned for method chaining
123 public function setSiteId($id) {
130 * Get Site Id set for SOAP communications with NewCrop
131 * @return string The Site Id sent with SOAP requests to NewCrop
133 public function getSiteId() {
134 if(null === $this->siteId
)
135 $this->siteId
= $this->getStore()
136 ->selectFederalEin();
138 return $this->siteId
;
142 * Get the authenticated users ID and NPI
143 * @return array The users ID and NPI
145 public function getAuthUserDetails() {
146 if(null === $this->authUserDetails
)
147 $this->authUserDetails
= $this->getStore()
148 ->getUserById($this->getAuthUserId());
150 return $this->authUserDetails
;
154 * Set the Id of the authenticated user
155 * @param integer $user The Id for the authenticated user
156 * @return eRxSOAP This object is returned for method chaining
158 public function setAuthUserId($user) {
159 $this->authUserId
= $user;
165 * Get the Id of the authenticated user
166 * @return integer The Id of the authenticated user
168 public function getAuthUserId() {
169 return $this->authUserId
;
173 * Set the Id of the current patient
174 * @param integer $id The Id of the current patient
175 * @return eRxSOAP This object is returned for method chaining
177 public function setPatientId($id) {
178 $this->patientId
= (integer) $id;
184 * Get the Id of the current patient
185 * @return integer The Id of the current patient
187 public function getPatientId() {
188 if(null === $this->patientId
) {
189 if(array_key_exists('patient', $_REQUEST))
190 $this->patientId
= $_REQUEST['patient'];
191 elseif(array_key_exists('pid', $GLOBALS))
192 $this->patientId
= $GLOBALS['pid'];
195 return $this->patientId
;
199 * Set the credentials for SOAP requests
200 * @param array $credentials Set of credentials: index [0 = Partner Name, 1 = eRx Name, 2 = eRx Password]
201 * @return eRxSOAP This object is returned for method chaining
203 public function setCredentials($credentials) {
204 $this->credentials
= $credentials;
210 * Get the credentials for SOAP requests
211 * @return array Set of credentials: index [0 = Partner Name, 1 = eRx Name, 2 = eRx Password]
213 public function getCredentials() {
214 return $this->credentials
;
218 * Set SOAP Web Service Address paths
219 * @param array $path Set of paths: index [0 = Update, 1 = Patient]
220 * @return eRxSOAP This object is returned for method chaining
222 public function setSoapPath($path) {
223 $this->soapPath
= (array) $path;
229 * Get SOAP Web Service Address paths
230 * @return array Set of paths: index [0 = Update, 1 = Patient]
232 public function getSoapPath() {
233 return $this->soapPath
;
237 * Generate and set a new SOAP client with provided Path Id
238 * @param integer $pathId Id for path set with getSoapPath: index [0 = Update, 1 = Patient]
239 * @return SoapClient Soap Client
241 public function initializeSoapClient($pathId) {
242 return $this->setSoapClient(new SoapClient($this->soapPath
[(integer) $pathId]));
246 * Set SOAP client for communication with NewCrop
247 * @param SoapClient $client SOAP client for communication with NewCrop
248 * @return eRxSOAP This object is returned for method chaining
250 public function setSoapClient(SoapClient
$client) {
251 $this->soapClient
= $client;
257 * Get SOAP client for communication with NewCrop
258 * @return SoapClient SOAP client for communication with NewCrop
260 public function getSoapClient() {
261 return $this->soapClient
;
265 * Set SOAP call settings for calls to NewCrop
266 * @param array $settings [optional] Setting to send with SOAP call to NewCrop
267 * @return eRxSOAP This object is returned for method chaining
269 public function setSoapSettings($settings = array()) {
270 $this->soapSettings
= (array) $settings;
276 * Get SOAP call settings for calls to NewCrop
277 * @return array Settings to send with SOAP call to NewCrop
279 public function &getSoapSettings() {
280 return $this->soapSettings
;
284 * Get TTL for provided SOAP process
285 * @param string $process SOAP process to retrieve TTL for
286 * @return number|boolean Number on success, false on failure
288 public function getTTL($process) {
289 if(array_key_exists('erx_soap_ttl_'.$process, $GLOBALS))
290 return $GLOBALS['erx_soap_ttl_'.$process];
296 * Check if TTL of current patient has elapsed for provided SOAP process
297 * @param string $process SOAP process to check against for elapsed TTL of current patient
298 * @return boolean True if TTL of current patient has elapsed for provided SOAP process, otherwise false
300 public function elapsedTTL($process) {
301 $ttl = $this->getTTL($process);
302 if(false === $ttl ||
0 == $ttl)
305 $soap = $this->getStore()->getLastSOAP($process, $this->getPatientId());
309 return strtotime('-'.$ttl.' seconds') >= strtotime($soap);
313 * Update provided SOAP process TTL timestamp of current patient
314 * @param string $process SOAP process to update TTL of current patient
315 * @return eRxSOAP This object is returned for method chaining
317 public function updateTTL($process) {
318 $this->getStore()->setLastSOAP($process, $this->getPatientId());
324 * Check if import status of current patient is set to provided SOAP process(es)
325 * @param string|array $status SOAP process to check against import status of current patient, optionally an array of SOAP processes can be substituted
326 * @return boolean True if import status of current patient is set to provided SOAP process(es), otherwise false
328 public function checkPatientImportStatus($status) {
329 $currentStatus = $this->getStore()
330 ->getPatientImportStatusByPatientId(
331 $this->getPatientId()
334 if(is_array($status))
335 $return = in_array($currentStatus, $status);
337 $return = ($currentStatus == $status);
343 * [updatePatientImportStatus description]
344 * @param string $status SOAP process to update import status of current patient
345 * @return eRxSOAP This object is returned for method chaining
347 public function updatePatientImportStatus($status) {
349 ->updatePatientImportStatusByPatientId(
350 $this->getPatientId(),
358 * Initialize SOAP settings with the credentials currently set
359 * @return eRxSOAP This object is returned for method chaining
361 public function initializeCredentials() {
362 $this->soapSettings
['credentials'] = array(
363 'PartnerName' => $this->credentials
['0'],
364 'Name' => $this->credentials
['1'],
365 'Password' => $this->credentials
['2'],
372 * Initialize SOAP settings with the NewCrop account and site Ids
373 * @return eRxSOAP This object is returned for method chaining
375 public function initializeAccountRequest() {
376 $this->soapSettings
['accountRequest'] = array(
377 'AccountId' => $this->getAccountId(),
378 'SiteId' => $this->getSiteId(),
385 * Initialize SOAP settings with patient information
386 * @return eRxSOAP This object is returned for method chaining
388 public function initializePatientInformationRequester() {
389 $userDetails = $this->getAuthUserDetails();
391 $this->soapSettings
['patientInformationRequester'] = array(
392 'UserId' => $userDetails['id'],
400 * Get account status information for current patient
401 * @return object SOAP client response from NewCrop call
403 public function getAccountStatus() {
404 $this->setSoapSettings()
405 ->initializeCredentials()
406 ->initializeAccountRequest();
408 $userDetails = $this->getAuthUserDetails();
410 $this->soapSettings
['locationId'] = $this->getPatientId();
411 $this->soapSettings
['userId'] = $userDetails['npi'];
412 $this->soapSettings
['userType'] = 'P';
414 $this->initializeSoapClient(1);
416 return $this->getSoapClient()
417 ->GetAccountStatus($this->soapSettings
);
421 * Get allergy history for current patient
422 * @return object SOAP client response from NewCrop call
424 public function getPatientAllergyHistoryV3() {
425 $this->setSoapSettings()
426 ->initializeCredentials()
427 ->initializeAccountRequest()
428 ->initializePatientInformationRequester();
430 $this->soapSettings
['patientRequest']['PatientId'] = $this->getPatientId();
432 $this->initializeSoapClient(0);
434 return $this->getSoapClient()
435 ->GetPatientAllergyHistoryV3($this->soapSettings
);
439 * Get full medication history for current patient
440 * @return object SOAP client response from NewCrop call
442 public function getPatientFullMedicationHistory6() {
443 $this->setSoapSettings()
444 ->initializeCredentials()
445 ->initializeAccountRequest()
446 ->initializePatientInformationRequester();
448 $this->soapSettings
['patientRequest']['PatientId'] = $this->getPatientId();
450 $this->soapSettings
['prescriptionHistoryRequest'] = array(
451 'StartHistory' => '2011-01-01T00:00:00.000',
452 'EndHistory' => date('Y-m-d').'T23:59:59.000',
453 'PrescriptionStatus' => 'C',
454 'PrescriptionSubStatus' => '%',
455 'PrescriptionArchiveStatus' => 'N',
458 $this->soapSettings
['patientIdType'] = '';
459 $this->soapSettings
['includeSchema'] = '';
461 $this->initializeSoapClient(0);
463 return $this->getSoapClient()
464 ->GetPatientFullMedicationHistory6($this->soapSettings
);
468 * Get free form allergy history for current patient
469 * @return object SOAP client response from NewCrop call
471 public function getPatientFreeFormAllergyHistory() {
472 $this->setSoapSettings()
473 ->initializeCredentials()
474 ->initializeAccountRequest()
475 ->initializePatientInformationRequester();
477 $this->soapSettings
['patientRequest']['PatientId'] = $this->getPatientId();
479 $client = $this->initializeSoapClient(0);
481 return $this->getSoapClient()
482 ->GetPatientFreeFormAllergyHistory($this->soapSettings
);
486 * Insert list option if missing and return the associated option Id
487 * @param string $listId Id of list to reference
488 * @param string $title Title text to find
489 * @return string Option Id of selected list item
491 public function insertMissingListOptions($listId, $title) {
492 $store = $this->getStore();
494 $optionId = $store->selectOptionIdByTitle($listId, $title);
496 if(false === $optionId) {
497 $optionId = 1 +
$store->selectOptionIdsByListId($listId);
499 $store->insertListOptions($listId, $optionId, $title);
506 * Trigger Allergy History SOAP call to NewCrop for current patient and update local cached data
507 * @return integer Count of newly cached records
509 public function insertUpdateAllergies() {
510 $store = $this->getStore();
514 $allergyArray = self
::htmlFixXmlToArray(
515 $this->getPatientAllergyHistoryV3()
516 ->GetPatientAllergyHistoryV3Result
520 if(is_array($allergyArray)) {
521 foreach($allergyArray as $allergy) {
522 $optionId = $this->insertMissingListOptions(
524 $allergy['AllergySeverityName']
527 $allergySource = $store->selectAllergyErxSourceByPatientIdName(
528 $this->getPatientId(),
529 $allergy['AllergyName']
533 if(false === $allergySource) {
534 $store->insertAllergy(
535 $allergy['AllergyName'],
536 $allergy['AllergyId'],
537 $this->getPatientId(),
538 $this->getAuthUserId(),
543 } elseif(0 == $allergySource) {
544 $store->updateAllergyOutcomeExternalIdByPatientIdName(
546 $allergy['AllergyId'],
547 $this->getPatientId(),
548 $allergy['AllergyName']
551 $store->updateAllergyOutcomeByPatientIdExternalIdName(
553 $this->getPatientId(),
554 $allergy['AllergyId'],
555 $allergy['AllergyName']
560 $this->updatePatientAllergyEndDate($allergyArray);
563 return $insertedRows;
567 * Iterate through provided list of allergies and update records with end dates
568 * @param array $allergyArray List of allergies
569 * @return eRxSOAP This object is returned for method chaining
571 public function updatePatientAllergyEndDate($allergyArray) {
572 $store = $this->getStore();
573 $patientId = $this->getPatientId();
575 $resource = $store->selectActiveAllergiesByPatientId($patientId);
577 while($row = sqlFetchArray($resource)) {
580 foreach($allergyArray as $allergy) {
581 if(array_key_exists('AllergyName', $allergy) && $allergy['AllergyName'] == $row['title']) {
588 $store->updateAllergyEndDateByPatientIdListId(
598 * Update eRx uploaded status for current patient allergies
599 * @return boolean True on success, false on failure
601 public function updateUploadedErx() {
602 $patientFreeFormAllergyHistory = $this
603 ->getPatientFreeFormAllergyHistory()
604 ->GetPatientFreeFormAllergyHistoryResult
;
606 if(0 < $patientFreeFormAllergyHistory->result
->RowCount
) {
607 $response = $patientFreeFormAllergyHistory
608 ->patientFreeFormAllergyExtendedDetail
609 ->PatientFreeFormAllergyExtendedDetail
;
611 if(!is_array($response))
612 $response = array($response);
614 foreach($response as $response) {
616 ->updateErxUploadedByListId($response->ExternalId
);
620 return isset($response);
624 * Insert or update medications for current patient
625 * @return integer Count of newly cached records
627 public function insertUpdateMedications() {
628 $store = $this->getStore();
632 $medArray = self
::htmlFixXmlToArray(
633 $this->getPatientFullMedicationHistory6()
634 ->GetPatientFullMedicationHistory6Result
638 $store->updatePrescriptionsActiveByPatientId($this->getPatientId());
640 if(is_array($medArray)) {
641 foreach($medArray as $med) {
642 if($med['DosageForm'])
643 $optionIdDosageForm = $this->insertMissingListOptions(
649 $optionIdRoute = $this->insertMissingListOptions(
654 if($med['StrengthUOM'])
655 $optionIdStrengthUOM = $this->insertMissingListOptions(
660 if($med['DosageFrequencyDescription'])
661 $optionIdFrequencyDescription = $this->insertMissingListOptions(
663 $med['DosageFrequencyDescription']
666 $providerId = $store->selectUserIdByUserName($med['ExternalPhysicianID']);
668 $check = $store->selectPrescriptionIdByGuidPatientId(
669 $med['PrescriptionGuid'],
670 $med['ExternalPatientID']
673 $prescriptionId = '';
675 if(0 == sqlNumRows($check)) {
676 $prescriptionId = $store->insertPrescriptions(
680 $this->getAuthUserId(),
683 $optionIdStrengthUOM,
684 $optionIdFrequencyDescription
689 setListTouch($this->getPatientId(), 'prescription_erx');
691 $store->updatePrescriptions(
694 $this->getAuthUserId(),
697 $optionIdStrengthUOM,
698 $optionIdFrequencyDescription
702 $result = sqlFetchArray($check);
704 $prescriptionId = $result['id'];
710 $med['ExternalPatientID'],
717 return $insertedRows;