4 * interface/eRxSOAP.php Functions for interacting with NewCrop SOAP calls.
7 * @link http://www.open-emr.org
8 * @author Sam Likins <sam.likins@wsi-services.com>
9 * @copyright Copyright (c) 2015 Sam Likins <sam.likins@wsi-services.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 const ACTION_ALLERGIES
= 'allergies';
17 const ACTION_MEDICATIONS
= 'medications';
19 const FLAG_PRESCRIPTION_PRESS
= '1';
20 const FLAG_PRESCRIPTION_IMPORT
= '2';
21 const FLAG_ALLERGY_PRESS
= '3';
22 const FLAG_ALLERGY_IMPORT
= '4';
28 private $authUserDetails;
31 private $soapSettings = array();
34 protected static function fixHtmlEntities($array, $xmltoarray)
36 $encoded = json_encode($array);
37 $fixed = $xmltoarray->fix_html_entities($encoded);
38 return json_decode($fixed, true);
42 * Repair HTML/XML and return array
43 * @param string $xml XML for processing
44 * @return array|boolean Array on success, false on failure
46 public static function htmlFixXmlToArray($xml)
48 $xmltoarray = new xmltoarray_parser_htmlfix(); //create instance of class
50 $xmltoarray->xmlparser_setoption(XML_OPTION_SKIP_WHITE
, 1); //set options same as xml_parser_set_option
51 $xmltoarray->xmlparser_setoption(XML_OPTION_CASE_FOLDING
, 0);
53 $xmltoarray->xmlparser_fix_into_struct(base64_decode($xml)); //fixes html values for XML
55 $array = $xmltoarray->createArray(); //creates an array with fixed html values
57 $array = self
::fixHtmlEntities($array, $xmltoarray);
59 if (array_key_exists('NewDataSet', $array) && array_key_exists('Table', $array['NewDataSet'])) {
60 $array = $array['NewDataSet']['Table'];
69 * Set Globals for retrieving eRx global configurations
70 * @param object $globals The eRx Globals object to use for processing
71 * @return eRxPage This object is returned for method chaining
73 public function setGlobals($globals)
75 $this->globals
= $globals;
81 * Get Globals for retrieving eRx global configurations
82 * @return object The eRx Globals object to use for processing
84 public function getGlobals()
86 return $this->globals
;
90 * Set Store to handle eRx cashed data
91 * @param object $store The eRx Store object to use for processing
92 * @return eRxSOAP This object is returned for method chaining
94 public function setStore($store)
96 $this->store
= $store;
102 * Get Store for handling eRx cashed data
103 * @return object The eRx Store object to use for processing
105 public function getStore()
111 * Get Account Id set for SOAP communications with NewCrop
112 * @return string The Account Id sent with SOAP requests to NewCrop
114 public function getAccountId()
116 return $this->getGlobals()->getAccountId();
120 * Set SiteId for SOAP communications with NewCrop
121 * @param string $id The Site Id to send with SOAP requests to NewCrop
122 * @return eRxSOAP This object is returned for method chaining
124 public function setSiteId($id)
132 * Get Site Id set for SOAP communications with NewCrop
133 * @return string The Site Id sent with SOAP requests to NewCrop
135 public function getSiteId()
137 if (null === $this->siteId
) {
138 $this->siteId
= $this->getStore()
139 ->selectFederalEin();
142 return $this->siteId
;
146 * Get the authenticated users ID and NPI
147 * @return array The users ID and NPI
149 public function getAuthUserDetails()
151 if (null === $this->authUserDetails
) {
152 $this->authUserDetails
= $this->getStore()
153 ->getUserById($this->getAuthUserId());
156 return $this->authUserDetails
;
160 * Set the Id of the authenticated user
161 * @param integer $user The Id for the authenticated user
162 * @return eRxSOAP This object is returned for method chaining
164 public function setAuthUserId($user)
166 $this->authUserId
= $user;
172 * Get the Id of the authenticated user
173 * @return integer The Id of the authenticated user
175 public function getAuthUserId()
177 return $this->authUserId
;
181 * Set the Id of the current patient
182 * @param integer $id The Id of the current patient
183 * @return eRxSOAP This object is returned for method chaining
185 public function setPatientId($id)
187 $this->patientId
= (int) $id;
193 * Get the Id of the current patient
194 * @return integer The Id of the current patient
196 public function getPatientId()
198 return $this->patientId
;
202 * Generate and set a new SOAP client with provided Path Id
203 * @param integer $pathId Id for NewCrop eRx SOAP path: index [0 = Update, 1 = Patient]
204 * @return SoapClient Soap Client
206 public function initializeSoapClient($pathId)
208 $paths = $this->getGlobals()->getSoapPaths();
210 return $this->setSoapClient(new SoapClient($paths[(int) $pathId]));
214 * Set SOAP client for communication with NewCrop
215 * @param SoapClient $client SOAP client for communication with NewCrop
216 * @return eRxSOAP This object is returned for method chaining
218 public function setSoapClient(SoapClient
$client)
220 $this->soapClient
= $client;
226 * Get SOAP client for communication with NewCrop
227 * @return SoapClient SOAP client for communication with NewCrop
229 public function getSoapClient()
231 return $this->soapClient
;
235 * Set SOAP call settings for calls to NewCrop
236 * @param array $settings [optional] Setting to send with SOAP call to NewCrop
237 * @return eRxSOAP This object is returned for method chaining
239 public function setSoapSettings($settings = array())
241 $this->soapSettings
= (array) $settings;
247 * Get SOAP call settings for calls to NewCrop
248 * @return array Settings to send with SOAP call to NewCrop
250 public function &getSoapSettings()
252 return $this->soapSettings
;
256 * Get TTL for provided SOAP process
257 * @param string $process SOAP process to retrieve TTL for
258 * @return number|boolean Number on success, false on failure
260 public function getTTL($process)
263 case self
::ACTION_ALLERGIES
:
264 $return = $this->getGlobals()->getTTLSoapAllergies();
266 case self
::ACTION_MEDICATIONS
:
267 $return = $this->getGlobals()->getTTLSoapMedications();
277 * Check if TTL of current patient has elapsed for provided SOAP process
278 * @param string $process SOAP process to check against for elapsed TTL of current patient
279 * @return boolean True if TTL of current patient has elapsed for provided SOAP process, otherwise false
281 public function elapsedTTL($process)
283 $ttl = $this->getTTL($process);
284 if (false === $ttl ||
0 == $ttl) {
288 $soap = $this->getStore()->getLastSOAP($process, $this->getPatientId());
289 if (false === $soap) {
293 return strtotime('-' . $ttl . ' seconds') >= strtotime($soap);
297 * Update provided SOAP process TTL timestamp of current patient
298 * @param string $process SOAP process to update TTL of current patient
299 * @return eRxSOAP This object is returned for method chaining
301 public function updateTTL($process)
303 $this->getStore()->setLastSOAP($process, $this->getPatientId());
309 * Check if import status of current patient is set to provided SOAP process(es)
310 * @param string|array $status SOAP process to check against import status of current patient, optionally an array of SOAP processes can be substituted
311 * @return boolean True if import status of current patient is set to provided SOAP process(es), otherwise false
313 public function checkPatientImportStatus($status)
315 $currentStatus = $this->getStore()
316 ->getPatientImportStatusByPatientId(
317 $this->getPatientId()
320 if (is_array($status)) {
321 $return = in_array($currentStatus, $status);
323 $return = ($currentStatus == $status);
330 * [updatePatientImportStatus description]
331 * @param string $status SOAP process to update import status of current patient
332 * @return eRxSOAP This object is returned for method chaining
334 public function updatePatientImportStatus($status)
337 ->updatePatientImportStatusByPatientId(
338 $this->getPatientId(),
346 * Initialize SOAP settings with the credentials currently set
347 * @return eRxSOAP This object is returned for method chaining
349 public function initializeCredentials()
351 $credentials = $this->getGlobals()->getCredentials();
353 $this->soapSettings
['credentials'] = array(
354 'PartnerName' => $credentials['0'],
355 'Name' => $credentials['1'],
356 'Password' => $credentials['2'],
363 * Initialize SOAP settings with the NewCrop account and site Ids
364 * @return eRxSOAP This object is returned for method chaining
366 public function initializeAccountRequest()
368 $this->soapSettings
['accountRequest'] = array(
369 'AccountId' => $this->getGlobals()->getAccountId(),
370 'SiteId' => $this->getSiteId(),
377 * Initialize SOAP settings with patient information
378 * @return eRxSOAP This object is returned for method chaining
380 public function initializePatientInformationRequester()
382 $userDetails = $this->getAuthUserDetails();
384 $this->soapSettings
['patientInformationRequester'] = array(
385 'UserId' => $userDetails['id'],
393 * Get account status information for current patient
394 * @return object SOAP client response from NewCrop call
396 public function getAccountStatus()
398 $this->setSoapSettings()
399 ->initializeCredentials()
400 ->initializeAccountRequest();
402 $userDetails = $this->getAuthUserDetails();
404 $this->soapSettings
['locationId'] = $this->getPatientId();
405 $this->soapSettings
['userId'] = $userDetails['npi'];
406 $this->soapSettings
['userType'] = 'P';
408 $this->initializeSoapClient(1);
410 return $this->getSoapClient()
411 ->GetAccountStatus($this->soapSettings
);
415 * Get allergy history for current patient
416 * @return object SOAP client response from NewCrop call
418 public function getPatientAllergyHistoryV3()
420 $this->setSoapSettings()
421 ->initializeCredentials()
422 ->initializeAccountRequest()
423 ->initializePatientInformationRequester();
425 $this->soapSettings
['patientRequest']['PatientId'] = $this->getPatientId();
427 $this->initializeSoapClient(0);
429 return $this->getSoapClient()
430 ->GetPatientAllergyHistoryV3($this->soapSettings
);
434 * Get full medication history for current patient
435 * @return object SOAP client response from NewCrop call
437 public function getPatientFullMedicationHistory6()
439 $this->setSoapSettings()
440 ->initializeCredentials()
441 ->initializeAccountRequest()
442 ->initializePatientInformationRequester();
444 $this->soapSettings
['patientRequest']['PatientId'] = $this->getPatientId();
446 $this->soapSettings
['prescriptionHistoryRequest'] = array(
447 'StartHistory' => '2011-01-01T00:00:00.000',
448 'EndHistory' => date('Y-m-d') . 'T23:59:59.000',
449 'PrescriptionStatus' => 'C',
450 'PrescriptionSubStatus' => '%',
451 'PrescriptionArchiveStatus' => 'N',
454 $this->soapSettings
['patientIdType'] = '';
455 $this->soapSettings
['includeSchema'] = '';
457 $this->initializeSoapClient(0);
459 return $this->getSoapClient()
460 ->GetPatientFullMedicationHistory6($this->soapSettings
);
464 * Get free form allergy history for current patient
465 * @return object SOAP client response from NewCrop call
467 public function getPatientFreeFormAllergyHistory()
469 $this->setSoapSettings()
470 ->initializeCredentials()
471 ->initializeAccountRequest()
472 ->initializePatientInformationRequester();
474 $this->soapSettings
['patientRequest']['PatientId'] = $this->getPatientId();
476 $client = $this->initializeSoapClient(0);
478 return $this->getSoapClient()
479 ->GetPatientFreeFormAllergyHistory($this->soapSettings
);
483 * Insert list option if missing and return the associated option Id
484 * @param string $listId Id of list to reference
485 * @param string $title Title text to find
486 * @return string Option Id of selected list item
488 public function insertMissingListOptions($listId, $title)
490 $store = $this->getStore();
492 $optionId = $store->selectOptionIdByTitle($listId, $title);
494 if (false === $optionId) {
495 $optionId = 1 +
$store->selectOptionIdsByListId($listId);
497 $store->insertListOptions($listId, $optionId, $title);
504 * Trigger Allergy History SOAP call to NewCrop for current patient and update local cached data
505 * @return integer Count of newly cached records
507 public function insertUpdateAllergies()
509 $store = $this->getStore();
513 $allergyArray = self
::htmlFixXmlToArray(
514 $this->getPatientAllergyHistoryV3()
515 ->GetPatientAllergyHistoryV3Result
519 if (is_array($allergyArray)) {
520 foreach ($allergyArray as $allergy) {
521 $optionId = $this->insertMissingListOptions(
523 $allergy['AllergySeverityName']
526 $allergySource = $store->selectAllergyErxSourceByPatientIdName(
527 $this->getPatientId(),
528 $allergy['AllergyName']
532 if (false === $allergySource) {
533 $store->insertAllergy(
534 $allergy['AllergyName'],
535 $allergy['AllergyId'],
536 $this->getPatientId(),
537 $this->getAuthUserId(),
542 } elseif (0 == $allergySource) {
543 $store->updateAllergyOutcomeExternalIdByPatientIdName(
545 $allergy['AllergyId'],
546 $this->getPatientId(),
547 $allergy['AllergyName']
550 $store->updateAllergyOutcomeByPatientIdExternalIdName(
552 $this->getPatientId(),
553 $allergy['AllergyId'],
554 $allergy['AllergyName']
559 $this->updatePatientAllergyEndDate($allergyArray);
562 return $insertedRows;
566 * Iterate through provided list of allergies and update records with end dates
567 * @param array $allergyArray List of allergies
568 * @return eRxSOAP This object is returned for method chaining
570 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(
599 * Update eRx uploaded status for current patient allergies
600 * @return boolean True on success, false on failure
602 public function updateUploadedErx()
604 $patientFreeFormAllergyHistory = $this
605 ->getPatientFreeFormAllergyHistory()
606 ->GetPatientFreeFormAllergyHistoryResult
;
608 if (0 < $patientFreeFormAllergyHistory->result
->RowCount
) {
609 $response = $patientFreeFormAllergyHistory
610 ->patientFreeFormAllergyExtendedDetail
611 ->PatientFreeFormAllergyExtendedDetail
;
613 if (!is_array($response)) {
614 $response = array($response);
617 foreach ($response as $response) {
619 ->updateErxUploadedByListId($response->ExternalId
);
623 return isset($response);
627 * Insert or update medications for current patient
628 * @return integer Count of newly cached records
630 public function insertUpdateMedications()
632 $store = $this->getStore();
636 $medArray = self
::htmlFixXmlToArray(
637 $this->getPatientFullMedicationHistory6()
638 ->GetPatientFullMedicationHistory6Result
641 $store->updatePrescriptionsActiveByPatientId($this->getPatientId());
642 if (is_array($medArray)) {
643 foreach ($medArray as $med) {
644 if ($med['DosageForm']) {
645 $optionIdDosageForm = $this->insertMissingListOptions(
650 $optionIdDosageForm = null;
654 $optionIdRoute = $this->insertMissingListOptions(
659 $optionIdRoute = null;
662 if ($med['StrengthUOM']) {
663 $optionIdStrengthUOM = $this->insertMissingListOptions(
668 $optionIdStrengthUOM = null;
671 if ($med['DosageFrequencyDescription']) {
672 $optionIdFrequencyDescription = $this->insertMissingListOptions(
674 $med['DosageFrequencyDescription']
677 $optionIdFrequencyDescription = null;
680 $providerId = $store->selectUserIdByUserName($med['ExternalPhysicianID']);
682 $check = $store->selectPrescriptionIdByGuidPatientId(
683 $med['PrescriptionGuid'],
684 $med['ExternalPatientID']
687 $prescriptionId = '';
689 if (0 == sqlNumRows($check)) {
690 $prescriptionId = $store->insertPrescriptions(
694 $this->getAuthUserId(),
697 $optionIdStrengthUOM,
698 $optionIdFrequencyDescription
703 setListTouch($this->getPatientId(), 'prescription_erx');
705 $store->updatePrescriptions(
708 $this->getAuthUserId(),
711 $optionIdStrengthUOM,
712 $optionIdFrequencyDescription
716 $result = sqlFetchArray($check);
718 $prescriptionId = $result['id'];
721 // Making sure only transmitted prescriptions entry added into amc_misc_data for eRx Numerator
722 if (!empty($med['PharmacyNCPDP'])) {
727 $med['ExternalPatientID'],
733 if ($med['FormularyChecked'] === 'true') {
734 processAmcCall('e_prescribe_chk_formulary_amc', true, 'add', $med['ExternalPatientID'], 'prescriptions', $prescriptionId);
739 return $insertedRows;