Fix to clear LBF form data that is not returned by the form but is defined in its...
[openemr.git] / interface / eRxSOAP.php
blob522f2645cae4ebbe493f4acd4326b0d2edc3af77
1 <?php
3 /**
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>.
18 * @package OpenEMR
19 * @subpackage NewCrop
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');
29 class eRxSOAP {
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';
39 private $store;
40 private $authUserId;
41 private $authUserDetails;
42 private $patientId;
43 private $credentials;
44 private $soapPath;
45 private $soapClient;
46 private $soapSettings = array();
47 private $accountId;
48 private $siteId;
50 /**
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'];
71 else
72 $array = false;
74 return $array;
77 /**
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;
85 return $this;
88 /**
89 * Get Store for handling eRx cashed data
90 * @return object The eRx Store object to use for processing
92 public function getStore() {
93 return $this->store;
96 /**
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;
104 return $this;
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) {
124 $this->siteId = $id;
126 return $this;
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;
161 return $this;
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;
180 return $this;
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;
206 return $this;
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;
225 return $this;
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;
253 return $this;
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;
272 return $this;
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];
291 else
292 return false;
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)
303 return true;
305 $soap = $this->getStore()->getLastSOAP($process, $this->getPatientId());
306 if(false === $soap)
307 return true;
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());
320 return $this;
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);
336 else
337 $return = ($currentStatus == $status);
339 return $return;
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) {
348 $this->getStore()
349 ->updatePatientImportStatusByPatientId(
350 $this->getPatientId(),
351 $status
354 return $this;
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'],
368 return $this;
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(),
381 return $this;
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'],
393 'UserType' => 'D',
396 return $this;
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);
502 return $optionId;
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();
512 $insertedRows = 0;
514 $allergyArray = self::htmlFixXmlToArray(
515 $this->getPatientAllergyHistoryV3()
516 ->GetPatientAllergyHistoryV3Result
517 ->XmlResponse
520 if(is_array($allergyArray)) {
521 foreach($allergyArray as $allergy) {
522 $optionId = $this->insertMissingListOptions(
523 'outcome',
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(),
539 $optionId
542 ++$insertedRows;
543 } elseif(0 == $allergySource) {
544 $store->updateAllergyOutcomeExternalIdByPatientIdName(
545 $optionId,
546 $allergy['AllergyId'],
547 $this->getPatientId(),
548 $allergy['AllergyName']
550 } else {
551 $store->updateAllergyOutcomeByPatientIdExternalIdName(
552 $optionId,
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)) {
578 $noMatch = true;
580 foreach($allergyArray as $allergy) {
581 if(array_key_exists('AllergyName', $allergy) && $allergy['AllergyName'] == $row['title']) {
582 $noMatch = false;
583 break;
587 if($noMatch)
588 $store->updateAllergyEndDateByPatientIdListId(
589 $patientId,
590 $row['id']
594 return $this;
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) {
615 $this->getStore()
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();
630 $insertedRows = 0;
632 $medArray = self::htmlFixXmlToArray(
633 $this->getPatientFullMedicationHistory6()
634 ->GetPatientFullMedicationHistory6Result
635 ->XmlResponse
638 $store->updatePrescriptionsActiveByPatientId($this->getPatientId());
640 if(is_array($medArray)) {
641 foreach($medArray as $med) {
642 if($med['DosageForm'])
643 $optionIdDosageForm = $this->insertMissingListOptions(
644 'drug_form',
645 $med['DosageForm']
648 if($med['Route'])
649 $optionIdRoute = $this->insertMissingListOptions(
650 'drug_route',
651 $med['Route']
654 if($med['StrengthUOM'])
655 $optionIdStrengthUOM = $this->insertMissingListOptions(
656 'drug_units',
657 $med['StrengthUOM']
660 if($med['DosageFrequencyDescription'])
661 $optionIdFrequencyDescription = $this->insertMissingListOptions(
662 'drug_interval',
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(
677 $med,
678 $encounter,
679 $providerId,
680 $this->getAuthUserId(),
681 $optionIdDosageForm,
682 $optionIdRoute,
683 $optionIdStrengthUOM,
684 $optionIdFrequencyDescription
687 ++$insertedRows;
689 setListTouch($this->getPatientId(), 'prescription_erx');
690 } else {
691 $store->updatePrescriptions(
692 $med,
693 $providerId,
694 $this->getAuthUserId(),
695 $optionIdDosageForm,
696 $optionIdRoute,
697 $optionIdStrengthUOM,
698 $optionIdFrequencyDescription
702 $result = sqlFetchArray($check);
703 if($result['id'])
704 $prescriptionId = $result['id'];
706 processAmcCall(
707 'e_prescribe_amc',
708 true,
709 'add',
710 $med['ExternalPatientID'],
711 'prescriptions',
712 $prescriptionId
717 return $insertedRows;