if (!$catid) { continue; } echo xlt('Fetching following file from portal') . ": " . $filename . " ...<br />\n"; flush(); if ($messageid) { $result = cms_portal_call(array('action' => 'getmsgup', 'uploadid' => $uploadid)); } else { $result = cms_portal_call(array('action' => 'getupload', 'uploadid' => $uploadid)); } if ($result['errmsg']) { die(text($result['errmsg'])); } $d = new Document(); // With JSON-over-HTTP we would need to base64_decode the contents. $rc = $d->createDocument($ptid, $catid, $filename, $result['mimetype'], $result['contents']); if ($rc) { die(text(xl('Error saving document') . ": {$rc}")); } } } // Finally, delete the request or message from the portal. if ($messageid) { $result = cms_portal_call(array('action' => 'delmessage', 'messageid' => $messageid)); } else { $result = cms_portal_call(array('action' => 'delpost', 'postid' => $postid)); } if ($result['errmsg']) { die(text($result['errmsg'])); } echo "<script language='JavaScript'>\n";
function upload_action_process() { // Collect a manually set owner if this has been set // Used when want to manually assign the owning user/service such as the Direct mechanism $non_HTTP_owner = false; if ($this->manual_set_owner) { $non_HTTP_owner = $this->manual_set_owner; } $couchDB = false; $harddisk = false; if ($GLOBALS['document_storage_method'] == 0) { $harddisk = true; } if ($GLOBALS['document_storage_method'] == 1) { $couchDB = true; } if ($_POST['process'] != "true") { return; } $doDecryption = false; $encrypted = $_POST['encrypted']; $passphrase = $_POST['passphrase']; if (!$GLOBALS['hide_document_encryption'] && $encrypted && $passphrase) { $doDecryption = true; } if (is_numeric($_POST['category_id'])) { $category_id = $_POST['category_id']; } $patient_id = 0; if (isset($_GET['patient_id']) && !$couchDB) { $patient_id = $_GET['patient_id']; } else { if (is_numeric($_POST['patient_id'])) { $patient_id = $_POST['patient_id']; } } $sentUploadStatus = array(); if (count($_FILES['file']['name']) > 0) { $upl_inc = 0; foreach ($_FILES['file']['name'] as $key => $value) { $fname = $value; $err = ""; if ($_FILES['file']['error'][$key] > 0 || empty($fname) || $_FILES['file']['size'][$key] == 0) { $fname = $value; if (empty($fname)) { $fname = htmlentities("<empty>"); } $error = "Error number: " . $_FILES['file']['error'][$key] . " occured while uploading file named: " . $fname . "\n"; if ($_FILES['file']['size'][$key] == 0) { $error .= "The system does not permit uploading files of with size 0.\n"; } } else { $tmpfile = fopen($_FILES['file']['tmp_name'][$key], "r"); $filetext = fread($tmpfile, $_FILES['file']['size'][$key]); fclose($tmpfile); if ($doDecryption) { $filetext = $this->decrypt($filetext, $passphrase); } if ($_POST['destination'] != '') { $fname = $_POST['destination']; } $d = new Document(); $rc = $d->createDocument($patient_id, $category_id, $fname, $_FILES['file']['type'][$key], $filetext, empty($_GET['higher_level_path']) ? '' : $_GET['higher_level_path'], empty($_POST['path_depth']) ? 1 : $_POST['path_depth'], $non_HTTP_owner); if ($rc) { $error .= $rc . "\n"; } else { $this->assign("upload_success", "true"); } $sentUploadStatus[] = $d; $this->assign("file", $sentUploadStatus); } // Option to run a custom plugin for each file upload. // This was initially created to delete the original source file in a custom setting. $upload_plugin = $GLOBALS['OE_SITE_DIR'] . "/documentUpload.plugin.php"; if (file_exists($upload_plugin)) { include_once $upload_plugin; } $upload_plugin_pp = 'documentUploadPostProcess'; if (function_exists($upload_plugin_pp)) { $tmp = call_user_func($upload_plugin_pp, $value, $d); if ($tmp) { $error = $tmp; } } // Following is just an example of code in such a plugin file. /***************************************************** function documentUploadPostProcess($filename, &$d) { $userid = $_SESSION['authUserID']; $row = sqlQuery("SELECT username FROM users WHERE id = ?", array($userid)); $owner = strtolower($row['username']); $dn = '1_' . ucfirst($owner); $filepath = "/shared_network_directory/$dn/$filename"; if (@unlink($filepath)) return ''; return "Failed to delete '$filepath'."; } *****************************************************/ } } $this->assign("error", nl2br($error)); //$this->_state = false; $_POST['process'] = ""; //return $this->fetch($GLOBALS['template_dir'] . "documents/" . $this->template_mod . "_upload.html"); }
/** * Parse and save. * * @param string &$hl7 The input HL7 text * @param string &$matchreq Array of shared patient matching requests * @param int $lab_id Lab ID * @param char $direction B=Bidirectional, R=Results-only * @param bool $dryrun True = do not update anything, just report errors * @param array $matchresp Array of responses to match requests; key is relative segment number, * value is an existing pid or 0 to specify creating a patient * @return array Array of errors and match requests, if any */ function receive_hl7_results(&$hl7, &$matchreq, $lab_id = 0, $direction = 'B', $dryrun = false, $matchresp = NULL) { global $rhl7_return; // This will hold returned error messages and related variables. $rhl7_return = array(); $rhl7_return['mssgs'] = array(); $rhl7_return['needmatch'] = false; // indicates if this file is pending a match request $rhl7_segnum = 0; if (substr($hl7, 0, 3) != 'MSH') { return rhl7LogMsg(xl('Input does not begin with a MSH segment'), true); } // This array holds everything to be written to the database. // We save and postpone these writes in case of errors while processing the message, // so we can look up data from parent results when child results are encountered, // and for other logic simplification. // Each element of this array is another array containing the following possible keys: // 'rep' - row of data to write to procedure_report // 'res' - array of rows to write to procedure_result for this procedure_report // 'fid' - unique lab-provided identifier for this report // $amain = array(); // End-of-line delimiter for text in procedure_result.comments and other multi-line notes. $commentdelim = "\n"; // Ensoftek: Different labs seem to send different EOLs. Edit HL7 input to a character we know. $hl7 = (string) str_replace(array("\r\n", "\r", "\n"), "\r", $hl7); $today = time(); $in_message_id = ''; $in_ssn = ''; $in_dob = ''; $in_lname = ''; $in_fname = ''; $in_orderid = 0; $in_procedure_code = ''; $in_report_status = ''; $in_encounter = 0; $patient_id = 0; // for results-only patient matching logic $porow = false; $pcrow = false; $oprow = false; $code_seq_array = array(); // tracks sequence numbers of order codes $results_category_id = 0; // document category ID for lab results // This is so we know where we are if a segment like NTE that can appear in // different places is encountered. $context = ''; // This will be "ORU" or "MDM". $msgtype = ''; // Stuff collected for MDM documents. $mdm_datetime = ''; $mdm_docname = ''; $mdm_text = ''; // Delimiters $d0 = "\r"; $d1 = substr($hl7, 3, 1); // typically | $d2 = substr($hl7, 4, 1); // typically ^ $d3 = substr($hl7, 5, 1); // typically ~ $d4 = substr($hl7, 6, 1); // typically \ $d5 = substr($hl7, 7, 1); // typically & // We'll need the document category IDs for any embedded documents. $catrow = sqlQuery("SELECT id FROM categories WHERE name = ?", array($GLOBALS['lab_results_category_name'])); if (empty($catrow['id'])) { return rhl7LogMsg(xl('Document category for lab results does not exist') . ': ' . $GLOBALS['lab_results_category_name'], true); } else { $results_category_id = $catrow['id']; $mdm_category_id = $results_category_id; $catrow = sqlQuery("SELECT id FROM categories WHERE name = ?", array($GLOBALS['gbl_mdm_category_name'])); if (!empty($catrow['id'])) { $mdm_category_id = $catrow['id']; } } $segs = explode($d0, $hl7); foreach ($segs as $seg) { if (empty($seg)) { continue; } // echo "<!-- $dryrun $seg -->\n"; // debugging ++$rhl7_segnum; $a = explode($d1, $seg); if ($a[0] == 'MSH') { if (!$dryrun) { rhl7FlushMain($amain, $commentdelim); } $amain = array(); if ('MDM' == $msgtype && !$dryrun) { $rc = rhl7FlushMDM($patient_id, $mdm_docname, $mdm_datetime, $mdm_text, $mdm_category_id, $oprow ? $oprow['username'] : 0); if ($rc) { return rhl7LogMsg($rc); } $patient_id = 0; } $context = $a[0]; // Ensoftek: Could come is as 'ORU^R01^ORU_R01'. Handle all cases when 'ORU^R01' is seen. if (strstr($a[8], "ORU^R01")) { $msgtype = 'ORU'; } else { if ($a[8] == 'MDM^T02' || $a[8] == 'MDM^T04' || $a[8] == 'MDM^T08') { $msgtype = 'MDM'; $mdm_datetime = ''; $mdm_docname = ''; $mdm_text = ''; } else { return rhl7LogMsg(xl('MSH.8 message type is not supported') . ": '" . $a[8] . "'", true); } } $in_message_id = $a[9]; } else { if ($a[0] == 'PID') { $context = $a[0]; if ('MDM' == $msgtype && !$dryrun) { $rc = rhl7FlushMDM($patient_id, $mdm_docname, $mdm_datetime, $mdm_text, $mdm_category_id, $oprow ? $oprow['username'] : 0); if ($rc) { return rhl7LogMsg($rc); } } $porow = false; $pcrow = false; $oprow = false; $in_orderid = 0; $in_ssn = preg_replace('/[^0-9]/', '', $a[4]); $in_dob = rhl7Date($a[7]); $tmp = explode($d2, $a[5]); $in_lname = rhl7Text($tmp[0]); $in_fname = rhl7Text($tmp[1]); $in_mname = rhl7Text($tmp[2]); $patient_id = 0; // Patient matching is needed for a results-only interface or MDM message type. if ('R' == $direction || 'MDM' == $msgtype) { $ptarr = array('ss' => strtoupper($in_ss), 'fname' => strtoupper($in_fname), 'lname' => strtoupper($in_lname), 'mname' => strtoupper($in_mname), 'DOB' => strtoupper($in_dob)); $patient_id = match_patient($ptarr); if ($patient_id == -1) { // Result is indeterminate. // Make a stringified form of $ptarr to use as a key. $ptstring = serialize($ptarr); // Check if the user has specified the patient. if (isset($matchresp[$ptstring])) { // This will be an existing pid, or 0 to specify creating a patient. $patient_id = intval($matchresp[$ptstring]); } else { if ($dryrun) { // Nope, ask the user to match. $matchreq[$ptstring] = true; $rhl7_return['needmatch'] = true; } else { // Should not happen, but it would be bad to abort now. Create the patient. $patient_id = 0; rhl7LogMsg(xl('Unexpected non-match, creating new patient for segment') . ' ' . $rhl7_segnum, false); } } } if ($patient_id == 0 && !$dryrun) { // We must create the patient. $patient_id = create_skeleton_patient($ptarr); } if ($patient_id == -1) { $patient_id = 0; } } // end results-only/MDM logic } else { if ('PD1' == $a[0]) { // TBD: Save primary care provider name ($a[4]) somewhere? } else { if ('PV1' == $a[0]) { if ('ORU' == $msgtype) { // Save placer encounter number if present. if ($direction != 'R' && !empty($a[19])) { $tmp = explode($d2, $a[19]); $in_encounter = intval($tmp[0]); } } else { if ('MDM' == $msgtype) { // For documents we want the ordering provider. // Try Referring Provider first. $oprow = match_provider(explode($d2, $a[8])); // If no match, try Other Provider. if (empty($oprow)) { $oprow = match_provider(explode($d2, $a[52])); } } } } else { if ('ORC' == $a[0] && 'ORU' == $msgtype) { $context = $a[0]; $arep = array(); $porow = false; $pcrow = false; if ($direction != 'R' && $a[2]) { $in_orderid = intval($a[2]); } } else { if ('TXA' == $a[0] && 'MDM' == $msgtype) { $context = $a[0]; $mdm_datetime = rhl7DateTime($a[4]); $mdm_docname = rhl7Text($a[12]); } else { if ($a[0] == 'NTE' && ($context == 'ORC' || $context == 'TXA')) { // Is this ever used? } else { if ('OBR' == $a[0] && 'ORU' == $msgtype) { $context = $a[0]; $arep = array(); if ($direction != 'R' && $a[2]) { $in_orderid = intval($a[2]); $porow = false; $pcrow = false; } $tmp = explode($d2, $a[4]); $in_procedure_code = $tmp[0]; $in_procedure_name = $tmp[1]; $in_report_status = rhl7ReportStatus($a[25]); // Filler identifier is supposed to be unique for each incoming report. $in_filler_id = $a[3]; // Child results will have these pointers to their parent. $in_parent_obrkey = ''; $in_parent_obxkey = ''; $parent_arep = false; // parent report, if any $parent_ares = false; // parent result, if any if (!empty($a[29])) { // This is a child so there should be a parent. $tmp = explode($d2, $a[29]); $in_parent_obrkey = str_replace($d5, $d2, $tmp[1]); $tmp = explode($d2, $a[26]); $in_parent_obxkey = str_replace($d5, $d2, $tmp[0]) . $d1 . $tmp[1]; // Look for the parent report. foreach ($amain as $arr) { if (isset($arr['fid']) && $arr['fid'] == $in_parent_obrkey) { $parent_arep = $arr['rep']; // Now look for the parent result within that report. foreach ($arr['res'] as $tmpres) { if (isset($tmpres['obxkey']) && $tmpres['obxkey'] == $in_parent_obxkey) { $parent_ares = $tmpres; break; } } break; } } } if ($parent_arep) { $in_orderid = $parent_arep['procedure_order_id']; } if ($direction == 'R') { // Save their order ID to procedure_order.control_id. // Look for an existing order using that plus lab_id. // Ordering provider is OBR.16 (NPI^Last^First). // Might not need to create a dummy encounter. // Need also provider_id (probably), patient_id, date_ordered, lab_id. // We have observation date/time in OBR.7. // We have report date/time in OBR.22. // We do not have an order date. $external_order_id = empty($a[2]) ? $a[3] : $a[2]; $porow = false; if (!$in_orderid && $external_order_id) { $porow = sqlQuery("SELECT * FROM procedure_order " . "WHERE lab_id = ? AND control_id = ? " . "ORDER BY procedure_order_id DESC LIMIT 1", array($lab_id, $external_order_id)); } if (!empty($porow)) { $in_orderid = intval($porow['procedure_order_id']); } if (!$in_orderid) { // Create order. // Need to identify the ordering provider and, if possible, a recent encounter. $datetime_report = rhl7DateTime($a[22]); $date_report = substr($datetime_report, 0, 10) . ' 00:00:00'; $encounter_id = 0; $provider_id = 0; // Look for the most recent encounter within 30 days of the report date. $encrow = sqlQuery("SELECT encounter FROM form_encounter WHERE " . "pid = ? AND date <= ? AND DATE_ADD(date, INTERVAL 30 DAY) > ? " . "ORDER BY date DESC, encounter DESC LIMIT 1", array($patient_id, $date_report, $date_report)); if (!empty($encrow)) { $encounter_id = intval($encrow['encounter']); $provider_id = intval($encrow['provider_id']); } if (!$provider_id) { // Attempt ordering provider matching by name or NPI. $oprow = match_provider(explode($d2, $a[16])); if (!empty($oprow)) { $provider_id = intval($oprow['id']); } } if (!$dryrun) { // Now create the procedure order. $in_orderid = sqlInsert("INSERT INTO procedure_order SET " . "date_ordered = ?, " . "provider_id = ?, " . "lab_id = ?, " . "date_collected = ?, " . "date_transmitted = ?, " . "patient_id = ?, " . "encounter_id = ?, " . "control_id = ?", array($datetime_report, $provider_id, $lab_id, rhl7DateTime($a[22]), rhl7DateTime($a[7]), $patient_id, $encounter_id, $external_order_id)); // If an encounter was identified then link the order to it. if ($encounter_id && $in_orderid) { addForm($encounter_id, "Procedure Order", $in_orderid, "procedure_order", $patient_id); } } } // end no $porow } // end results-only if (empty($porow)) { $porow = sqlQuery("SELECT * FROM procedure_order WHERE " . "procedure_order_id = ?", array($in_orderid)); // The order must already exist. Currently we do not handle electronic // results returned for manual orders. if (empty($porow) && !($dryrun && $direction == 'R')) { return rhl7LogMsg(xl('Procedure order not found') . ": {$in_orderid}", true); } if ($in_encounter) { if ($direction != 'R' && $porow['encounter_id'] != $in_encounter) { return rhl7LogMsg(xl('Encounter ID') . " '" . $porow['encounter_id'] . "' " . xl('for OBR placer order number') . " '{$in_orderid}' " . xl('does not match the PV1 encounter number') . " '{$in_encounter}'"); } } else { // They did not return an encounter number to verify, so more checking // might be done here to make sure the patient seems to match. } // Save the lab's control ID if there is one. $tmp = explode($d2, $a[3]); $control_id = $tmp[0]; if ($control_id && empty($porow['control_id'])) { sqlStatement("UPDATE procedure_order SET control_id = ? WHERE " . "procedure_order_id = ?", array($control_id, $in_orderid)); } $code_seq_array = array(); } // Find the order line item (procedure code) that matches this result. // If there is more than one, then we select the one whose sequence number // is next after the last sequence number encountered for this procedure // code; this assumes that result OBRs are returned in the same sequence // as the corresponding OBRs in the order. if (!isset($code_seq_array[$in_procedure_code])) { $code_seq_array[$in_procedure_code] = 0; } $pcquery = "SELECT pc.* FROM procedure_order_code AS pc " . "WHERE pc.procedure_order_id = ? AND pc.procedure_code = ? " . "ORDER BY (procedure_order_seq <= ?), procedure_order_seq LIMIT 1"; $pcqueryargs = array($in_orderid, $in_procedure_code, $code_seq_array[$in_procedure_code]); $pcrow = sqlQuery($pcquery, $pcqueryargs); if (empty($pcrow)) { // There is no matching procedure in the order, so it must have been // added after the original order was sent, either as a manual request // from the physician or as a "reflex" from the lab. // procedure_source = '2' indicates this. if (!$dryrun) { sqlBeginTrans(); $procedure_order_seq = sqlQuery("SELECT IFNULL(MAX(procedure_order_seq),0) + 1 AS increment FROM procedure_order_code WHERE procedure_order_id = ? ", array($in_orderid)); sqlInsert("INSERT INTO procedure_order_code SET " . "procedure_order_id = ?, " . "procedure_order_seq = ?, " . "procedure_code = ?, " . "procedure_name = ?, " . "procedure_source = '2'", array($in_orderid, $procedure_order_seq['increment'], $in_procedure_code, $in_procedure_name)); $pcrow = sqlQuery($pcquery, $pcqueryargs); sqlCommitTrans(); } else { // Dry run, make a dummy procedure_order_code row. $pcrow = array('procedure_order_id' => $in_orderid, 'procedure_order_seq' => 0); } } $code_seq_array[$in_procedure_code] = 0 + $pcrow['procedure_order_seq']; $arep = array(); $arep['procedure_order_id'] = $in_orderid; $arep['procedure_order_seq'] = $pcrow['procedure_order_seq']; $arep['date_collected'] = rhl7DateTime($a[7]); $arep['date_collected_tz'] = rhl7DateTimeZone($a[7]); $arep['date_report'] = rhl7DateTime($a[22]); $arep['date_report_tz'] = rhl7DateTimeZone($a[22]); $arep['report_status'] = $in_report_status; $arep['report_notes'] = ''; $arep['specimen_num'] = ''; // If this is a child report, add some info from the parent. if (!empty($parent_ares)) { $arep['report_notes'] .= xl('This is a child of result') . ' ' . $parent_ares['result_code'] . ' ' . xl('with value') . ' "' . $parent_ares['result'] . '".' . "\n"; } if (!empty($parent_arep)) { $arep['report_notes'] .= $parent_arep['report_notes']; $arep['specimen_num'] = $parent_arep['specimen_num']; } // Create the main array entry for this report and its results. $i = count($amain); $amain[$i] = array(); $amain[$i]['rep'] = $arep; $amain[$i]['fid'] = $in_filler_id; $amain[$i]['res'] = array(); } else { if ($a[0] == 'NTE' && $context == 'OBR') { // Append this note to those for the most recent report. $amain[count($amain) - 1]['rep']['report_notes'] .= rhl7Text($a[3], true) . "\n"; } else { if ('OBX' == $a[0] && 'ORU' == $msgtype) { $tmp = explode($d2, $a[3]); $result_code = rhl7Text($tmp[0]); $result_text = rhl7Text($tmp[1]); // If this is a text result that duplicates the previous result except // for its value, then treat it as an extension of that result's value. $i = count($amain) - 1; $j = count($amain[$i]['res']) - 1; if ($j >= 0 && $context == 'OBX' && $a[2] == 'TX' && $amain[$i]['res'][$j]['result_data_type'] == 'L' && $amain[$i]['res'][$j]['result_code'] == $result_code && $amain[$i]['res'][$j]['date'] == rhl7DateTime($a[14]) && $amain[$i]['res'][$j]['facility'] == rhl7Text($a[15]) && $amain[$i]['res'][$j]['abnormal'] == rhl7Abnormal($a[8]) && $amain[$i]['res'][$j]['result_status'] == rhl7ReportStatus($a[11])) { $amain[$i]['res'][$j]['comments'] = substr($amain[$i]['res'][$j]['comments'], 0, strlen($amain[$i]['res'][$j]['comments']) - 1) . '~' . rhl7Text($a[5]) . $commentdelim; continue; } $context = $a[0]; $ares = array(); $ares['result_data_type'] = substr($a[2], 0, 1); // N, S, F or E $ares['comments'] = $commentdelim; if ($a[2] == 'ED') { // This is the case of results as an embedded document. We will create // a normal patient document in the assigned category for lab results. $tmp = explode($d2, $a[5]); $fileext = strtolower($tmp[0]); $filename = date("Ymd_His") . '.' . $fileext; $data = rhl7DecodeData($tmp[3], $tmp[4]); if ($data === FALSE) { return rhl7LogMsg(xl('Invalid encapsulated data encoding type') . ': ' . $tmp[3]); } if (!$dryrun) { $d = new Document(); $rc = $d->createDocument($porow['patient_id'], $results_category_id, $filename, rhl7MimeType($fileext), $data); if ($rc) { return rhl7LogMsg($rc); } $ares['document_id'] = $d->get_id(); } } else { if ($a[2] == 'CWE') { $ares['result'] = rhl7CWE($a[5], $d2); } else { if ($a[2] == 'SN') { $ares['result'] = trim(str_replace($d2, ' ', $a[5])); } else { if ($a[2] == 'TX' || strlen($a[5]) > 200) { // OBX-5 can be a very long string of text with "~" as line separators. // The first line of comments is reserved for such things. $ares['result_data_type'] = 'L'; $ares['result'] = ''; $ares['comments'] = rhl7Text($a[5]) . $commentdelim; } else { $ares['result'] = rhl7Text($a[5]); } } } } $ares['result_code'] = $result_code; $ares['result_text'] = $result_text; $ares['date'] = rhl7DateTime($a[14]); $ares['facility'] = rhl7Text($a[15]); // Ensoftek: Units may have mutiple segments(as seen in MU2 samples), parse and take just first segment. $tmp = explode($d2, $a[6]); $ares['units'] = rhl7Text($tmp[0]); $ares['range'] = rhl7Text($a[7]); $ares['abnormal'] = rhl7Abnormal($a[8]); // values are lab dependent $ares['result_status'] = rhl7ReportStatus($a[11]); // Ensoftek: Performing Organization Details. Goes into "Pending Review/Patient Results--->Notes--->Facility" section. $performingOrganization = getPerformingOrganizationDetails($a[23], $a[24], $a[25], $d2, $commentdelim); if (!empty($performingOrganization)) { $ares['facility'] .= $performingOrganization . $commentdelim; } /**** // Probably need a better way to report this, if it matters. if (!empty($a[19])) { $ares['comments'] .= xl('Analyzed') . ' ' . rhl7DateTime($a[19]) . '.' . $commentdelim; } ****/ // obxkey is to allow matching this as a parent result. $ares['obxkey'] = $a[3] . $d1 . $a[4]; // Append this result to those for the most recent report. // Note the 'procedure_report_id' item is not yet present. $amain[count($amain) - 1]['res'][] = $ares; } else { if ('OBX' == $a[0] && 'MDM' == $msgtype) { $context = $a[0]; if ($a[2] == 'TX') { if ($mdm_text !== '') { $mdm_text .= "\r\n"; } $mdm_text .= rhl7Text($a[5]); } else { return rhl7LogMsg(xl('Unsupported MDM OBX result type') . ': ' . $a[2]); } } else { if ('ZEF' == $a[0] && 'ORU' == $msgtype) { // ZEF segment is treated like an OBX with an embedded Base64-encoded PDF. $context = 'OBX'; $ares = array(); $ares['result_data_type'] = 'E'; $ares['comments'] = $commentdelim; // $fileext = 'pdf'; $filename = date("Ymd_His") . '.' . $fileext; $data = rhl7DecodeData('Base64', $a[2]); if ($data === FALSE) { return rhl7LogMsg(xl('ZEF segment internal error')); } if (!$dryrun) { $d = new Document(); $rc = $d->createDocument($porow['patient_id'], $results_category_id, $filename, rhl7MimeType($fileext), $data); if ($rc) { return rhl7LogMsg($rc); } $ares['document_id'] = $d->get_id(); } $ares['date'] = $arep['date_report']; // $arep is left over from the OBR logic. // Append this result to those for the most recent report. // Note the 'procedure_report_id' item is not yet present. $amain[count($amain) - 1]['res'][] = $ares; } else { if ('NTE' == $a[0] && 'OBX' == $context && 'ORU' == $msgtype) { // Append this note to the most recent result item's comments. $alast = count($amain) - 1; $rlast = count($amain[$alast]['res']) - 1; $amain[$alast]['res'][$rlast]['comments'] .= rhl7Text($a[3], true) . $commentdelim; } else { if ('SPM' == $a[0] && 'ORU' == $msgtype) { rhl7UpdateReportWithSpecimen($amain, $a, $d2); } else { if ('TQ1' == $a[0] && 'ORU' == $msgtype) { // Ignore and do nothing. } else { return rhl7LogMsg(xl('Segment name') . " '{$a[0]}' " . xl('is misplaced or unknown')); } } } } } } } } } } } } } } } } // Write all reports and their results to the database. // This will do nothing if a dry run or MDM message type. if ('ORU' == $msgtype && !$dryrun) { rhl7FlushMain($amain, $commentdelim); } if ('MDM' == $msgtype && !$dryrun) { // Write documents. $rc = rhl7FlushMDM($patient_id, $mdm_docname, $mdm_datetime, $mdm_text, $mdm_category_id, $oprow ? $oprow['username'] : 0); if ($rc) { return rhl7LogMsg($rc); } } return $rhl7_return; }
//get A to Z class list for specific subject $orderedArray = $class2->getClassBySubject("Math"); printf("Ordered Classes by Subject - Math: \n"); foreach ($orderedArray as $class_val) { printf("%s\n", $class_val); } //////////////////////////// //Document UNIT TESTS //////////////////////////// printf("/////////////////////////////////\n"); printf("STARTING Document UNIT TESTS\n"); printf("/////////////////////////////////\n"); //construct empty document $document = new Document(); //add a document $document->createDocument("kmassey", "Distributed Client Server Prog", "Computer Science", "Test 1 Study Guide", ".pdf", "fake/path"); //delete document $document->deleteDocument(); //get document info $doc_id = $document->getDocID(); printf("Document's ID: %d\n", $doc_id); //new document from ID $document2 = new Document(1083097730); //get name from doc $doc_name = $document2->getDocName(); printf("Doc name retrieved: %s\n", $doc_name); //get current document scores printf("Upvotes: %d\n", $document2->getUpvotes()); printf("Downvotes: %d\n", $document2->getDownvotes()); //upvote printf("Upvoting...\n");
//this adds the file name and extension to the end of the path $target_path = $target_path . basename($_FILES['uploadedfile']['name']); $ext = pathinfo($target_path, PATHINFO_EXTENSION); //echo $ext; //only certain file types can be uploaded (constraint from ViewerJS) if ($ext == 'pdf' || $ext == 'ods' || $ext == 'odp' || $ext == 'odt') { //file that is uploaded is a temporary file. Need to copy the temp file to correct location if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file " . basename($_FILES['uploadedfile']['name']) . " has been uploaded"; } else { echo "There was an error uploading the file, please try again!"; } //allow for view after upload $view_path = 'Documents/' . $subject . '/' . $class . '/' . basename($_FILES['uploadedfile']['name']); $new_doc = new Document(); $new_doc->createDocument($_SESSION['username'], $class, $subject, $name, $ext, basename($_FILES['uploadedfile']['name'])); } else { echo "Please upload the correct file type. PDF, ODS, ODP, ODT."; } ?> <h2><?php echo $name; ?> </h2> <iframe src ="http://www.studyhallway.com/kite/apps/studyhall/ViewerJS/#../<?php echo $view_path; ?> "
/** * Parse and save. * * @param string &$hl7 The input HL7 text. * @param char $direction B=Bidirectional, R=Results-only * @param book $dryrun True = do not update anything, just report errors * @return array Array of errors and match requests, if any. */ function receive_hl7_results(&$hl7, $lab_id = 0, $direction = 'B', $dryrun = false, $matchresp = NULL) { // This will hold returned error messages and related variables. $rhl7_return = array(); $rhl7_return['mssgs'] = array(); $rhl7_return['match'] = array(); $rhl7_segnum = 0; if (substr($hl7, 0, 3) != 'MSH') { return rhl7LogMsg(xl('Input does not begin with a MSH segment'), true); } // End-of-line delimiter for text in procedure_result.comments $commentdelim = "\n"; $today = time(); $in_message_id = ''; $in_ssn = ''; $in_dob = ''; $in_lname = ''; $in_fname = ''; $in_orderid = 0; $in_procedure_code = ''; $in_report_status = ''; $in_encounter = 0; $patient_id = 0; // for results-only patient matching logic $porow = false; $pcrow = false; $procedure_report_id = 0; $arep = array(); // holding area for OBR and its NTE data $ares = array(); // holding area for OBX and its NTE data $code_seq_array = array(); // tracks sequence numbers of order codes $results_category_id = 0; // document category ID for lab results // This is so we know where we are if a segment like NTE that can appear in // different places is encountered. $context = ''; // Delimiters $d0 = "\r"; $d1 = substr($hl7, 3, 1); // typically | $d2 = substr($hl7, 4, 1); // typically ^ $d3 = substr($hl7, 5, 1); // typically ~ // We'll need the document category ID for any embedded documents. $catrow = sqlQuery("SELECT id FROM categories WHERE name = ?", array($GLOBALS['lab_results_category_name'])); if (empty($catrow['id'])) { return rhl7LogMsg(xl('Document category for lab results does not exist') . ': ' . $GLOBALS['lab_results_category_name'], true); } else { $results_category_id = $catrow['id']; } $segs = explode($d0, $hl7); foreach ($segs as $seg) { if (empty($seg)) { continue; } // echo "<!-- $dryrun $seg -->\n"; // debugging ++$rhl7_segnum; $a = explode($d1, $seg); if ($a[0] == 'MSH') { $context = $a[0]; if ($a[8] != 'ORU^R01') { return rhl7LogMsg(xl('MSH.8 message type is not valid') . ": '" . $a[8] . "'", true); } $in_message_id = $a[9]; } else { if ($a[0] == 'PID') { $context = $a[0]; if (!$dryrun) { rhl7FlushResult($ares); } $ares = array(); // Next line will do something only if there was a report with no results. if (!$dryrun) { rhl7FlushReport($arep); } $arep = array(); $porow = false; $pcrow = false; $in_orderid = 0; $in_ssn = preg_replace('/[^0-9]/', '', $a[4]); $in_dob = rhl7Date($a[7]); $tmp = explode($d2, $a[5]); $in_lname = rhl7Text($tmp[0]); $in_fname = rhl7Text($tmp[1]); $patient_id = 0; if ($direction == 'R') { $patient_id = match_patient($in_ss, $in_fname, $in_lname, $in_dob); if ($patient_id == -1) { // Indeterminate, check if the user has specified the patient. if (isset($matchresp[$rhl7_segnum])) { // This will be an existing pid, or 0 to specify creating a patient. $patient_id = intval($matchresp[$rhl7_segnum]); } else { // Nope, ask the user to do so. $rhl7_return['match'][$rhl7_segnum] = array('ss' => $in_ss, 'fname' => $in_fname, 'lname' => $in_lname, 'DOB' => $in_dob); } } if ($patient_id == 0 && !$dryrun) { // We must create the patient. $patient_id = create_skeleton_patient(array('fname' => $in_fname, 'lname' => $in_lname, 'DOB' => $in_dob, 'ss' => $in_ssn)); } if ($patient_id == -1) { $patient_id = 0; } } // end results-only logic } else { if ($a[0] == 'PV1') { // Save placer encounter number if present. if ($direction != 'R' && !empty($a[19])) { $tmp = explode($d2, $a[19]); $in_encounter = intval($tmp[0]); } } else { if ($a[0] == 'ORC') { $context = $a[0]; if (!$dryrun) { rhl7FlushResult($ares); } $ares = array(); // Next line will do something only if there was a report with no results. if (!$dryrun) { rhl7FlushReport($arep); } $arep = array(); $porow = false; $pcrow = false; if ($direction != 'R' && $a[2]) { $in_orderid = intval($a[2]); } } else { if ($a[0] == 'NTE' && $context == 'ORC') { // Is this ever used? } else { if ($a[0] == 'OBR') { $context = $a[0]; if (!$dryrun) { rhl7FlushResult($ares); } $ares = array(); // Next line will do something only if there was a report with no results. if (!$dryrun) { rhl7FlushReport($arep); } $arep = array(); $procedure_report_id = 0; if ($direction != 'R' && $a[2]) { $in_orderid = intval($a[2]); $porow = false; $pcrow = false; } $tmp = explode($d2, $a[4]); $in_procedure_code = $tmp[0]; $in_procedure_name = $tmp[1]; $in_report_status = rhl7ReportStatus($a[25]); // if ($direction == 'R') { // $in_orderid will be 0 here. // Save their order ID to procedure_order.control_id. // That column will need to change from bigint to varchar. // Look for an existing order using that plus lab_id. // Ordering provider is OBR.16 (NPI^Last^First). // Might not need to create a dummy encounter. // Need also provider_id (probably), patient_id, date_ordered, lab_id. // We have observation date/time in OBR.7. // We have report date/time in OBR.22. // We do not have an order date. $external_order_id = empty($a[2]) ? $a[3] : $a[2]; $porow = false; if ($external_order_id) { $porow = sqlQuery("SELECT * FROM procedure_order " . "WHERE lab_id = ? AND control_id = ? " . "ORDER BY procedure_order_id DESC LIMIT 1", array($lab_id, $external_order_id)); } if (!empty($porow)) { $in_orderid = intval($porow['procedure_order_id']); } else { // Create order. // Need to identify the ordering provider and, if possible, a recent encounter. $datetime_report = rhl7DateTime($a[22]); $date_report = substr($datetime_report, 0, 10) . ' 00:00:00'; $encounter_id = 0; $provider_id = 0; // Look for the most recent encounter within 30 days of the report date. $encrow = sqlQuery("SELECT encounter FROM form_encounter WHERE " . "pid = ? AND date <= ? AND DATE_ADD(date, INTERVAL 30 DAY) > ? " . "ORDER BY date DESC, encounter DESC LIMIT 1", array($patient_id, $date_report, $date_report)); if (!empty($encrow)) { $encounter_id = intval($encrow['encounter']); $provider_id = intval($encrow['provider_id']); } if (!$provider_id) { // Attempt ordering provider matching by name or NPI. $op_lname = $op_fname = ''; $tmp = explode($d2, $a[16]); $op_npi = preg_replace('/[^0-9]/', '', $tmp[0]); if (!empty($tmp[1])) { $op_lname = $tmp[1]; } if (!empty($tmp[2])) { $op_fname = $tmp[2]; } if ($op_npi || $op_fname && $op_lname) { if ($op_npi) { if ($op_fname && $op_lname) { $where = "(npi IS NOT NULL AND npi = ?) OR ((npi IS NULL OR npi = ?) AND lname = ? AND fname = ?)"; $qarr = array($op_npi, '', $op_lname, $op_fname); } else { $where = "npi IS NOT NULL AND npi = ?"; $qarr = array($op_npi); } } else { $where = "lname = ? AND fname = ?"; $qarr = array($op_lname, $op_fname); } } $oprow = sqlQuery("SELECT id FROM users WHERE {$where} " . "ORDER BY active DESC, authorized DESC, username DESC, id LIMIT 1", $qarr); if (!empty($oprow)) { $provider_id = intval($oprow['id']); } } if (!$dryrun) { // Now create the procedure order. $in_orderid = sqlInsert("INSERT INTO procedure_order SET " . "date_ordered = ?, " . "provider_id = ?, " . "lab_id = ?, " . "date_collected = ?, " . "date_transmitted = ?, " . "patient_id = ?, " . "encounter_id = ?, " . "control_id = ?", array($datetime_report, $provider_id, $lab_id, rhl7DateTime($a[22]), rhl7DateTime($a[7]), $patient_id, $encounter_id, $external_order_id)); // If an encounter was identified then link the order to it. if ($encounter_id && $in_orderid) { addForm($encounter_id, "Procedure Order", $in_orderid, "procedure_order", $patient_id); } } } // end no $porow } // end results-only if (empty($porow)) { $porow = sqlQuery("SELECT * FROM procedure_order WHERE " . "procedure_order_id = ?", array($in_orderid)); // The order must already exist. Currently we do not handle electronic // results returned for manual orders. if (empty($porow) && !($dryrun && $direction == 'R')) { return rhl7LogMsg(xl('Procedure order not found') . ": {$in_orderid}", true); } if ($in_encounter) { if ($direction != 'R' && $porow['encounter_id'] != $in_encounter) { return rhl7LogMsg(xl('Encounter ID') . " '" . $porow['encounter_id'] . "' " . xl('for OBR placer order number') . " '{$in_orderid}' " . xl('does not match the PV1 encounter number') . " '{$in_encounter}'"); } } else { // They did not return an encounter number to verify, so more checking // might be done here to make sure the patient seems to match. } // Save the lab's control ID if there is one. $tmp = explode($d2, $a[3]); $control_id = $tmp[0]; if ($control_id && empty($porow['control_id'])) { sqlStatement("UPDATE procedure_order SET control_id = ? WHERE " . "procedure_order_id = ?", array($control_id, $in_orderid)); } $code_seq_array = array(); } // Find the order line item (procedure code) that matches this result. // If there is more than one, then we select the one whose sequence number // is next after the last sequence number encountered for this procedure // code; this assumes that result OBRs are returned in the same sequence // as the corresponding OBRs in the order. if (!isset($code_seq_array[$in_procedure_code])) { $code_seq_array[$in_procedure_code] = 0; } $pcquery = "SELECT pc.* FROM procedure_order_code AS pc " . "WHERE pc.procedure_order_id = ? AND pc.procedure_code = ? " . "ORDER BY (procedure_order_seq <= ?), procedure_order_seq LIMIT 1"; $pcqueryargs = array($in_orderid, $in_procedure_code, $code_seq_array[$in_procedure_code]); $pcrow = sqlQuery($pcquery, $pcqueryargs); if (empty($pcrow)) { // There is no matching procedure in the order, so it must have been // added after the original order was sent, either as a manual request // from the physician or as a "reflex" from the lab. // procedure_source = '2' indicates this. if (!$dryrun) { sqlInsert("INSERT INTO procedure_order_code SET " . "procedure_order_id = ?, " . "procedure_code = ?, " . "procedure_name = ?, " . "procedure_source = '2'", array($in_orderid, $in_procedure_code, $in_procedure_name)); $pcrow = sqlQuery($pcquery, $pcqueryargs); } else { // Dry run, make a dummy procedure_order_code row. $pcrow = array('procedure_order_id' => $in_orderid, 'procedure_order_seq' => 0); } } $code_seq_array[$in_procedure_code] = 0 + $pcrow['procedure_order_seq']; $arep = array(); $arep['procedure_order_id'] = $in_orderid; $arep['procedure_order_seq'] = $pcrow['procedure_order_seq']; $arep['date_collected'] = rhl7DateTime($a[7]); $arep['date_report'] = rhl7Date($a[22]); $arep['report_status'] = $in_report_status; $arep['report_notes'] = ''; } else { if ($a[0] == 'NTE' && $context == 'OBR') { $arep['report_notes'] .= rhl7Text($a[3]) . "\n"; } else { if ($a[0] == 'OBX') { $context = $a[0]; if (!$dryrun) { rhl7FlushResult($ares); } $ares = array(); if (!$procedure_report_id) { if (!$dryrun) { $procedure_report_id = rhl7FlushReport($arep); } $arep = array(); } $ares['procedure_report_id'] = $procedure_report_id; $ares['result_data_type'] = substr($a[2], 0, 1); // N, S, F or E $ares['comments'] = $commentdelim; if ($a[2] == 'ED') { // This is the case of results as an embedded document. We will create // a normal patient document in the assigned category for lab results. $tmp = explode($d2, $a[5]); $fileext = strtolower($tmp[0]); $filename = date("Ymd_His") . '.' . $fileext; $data = rhl7DecodeData($tmp[3], $tmp[4]); if ($data === FALSE) { return rhl7LogMsg(xl('Invalid encapsulated data encoding type') . ': ' . $tmp[3]); } if (!$dryrun) { $d = new Document(); $rc = $d->createDocument($porow['patient_id'], $results_category_id, $filename, rhl7MimeType($fileext), $data); if ($rc) { return rhl7LogMsg($rc); } $ares['document_id'] = $d->get_id(); } } else { if (strlen($a[5]) > 200) { // OBX-5 can be a very long string of text with "~" as line separators. // The first line of comments is reserved for such things. $ares['result_data_type'] = 'L'; $ares['result'] = ''; $ares['comments'] = rhl7Text($a[5]) . $commentdelim; } else { $ares['result'] = rhl7Text($a[5]); } } $tmp = explode($d2, $a[3]); $ares['result_code'] = rhl7Text($tmp[0]); $ares['result_text'] = rhl7Text($tmp[1]); $ares['date'] = rhl7DateTime($a[14]); $ares['facility'] = rhl7Text($a[15]); $ares['units'] = rhl7Text($a[6]); $ares['range'] = rhl7Text($a[7]); $ares['abnormal'] = rhl7Abnormal($a[8]); // values are lab dependent $ares['result_status'] = rhl7ReportStatus($a[11]); } else { if ($a[0] == 'ZEF') { // ZEF segment is treated like an OBX with an embedded Base64-encoded PDF. $context = 'OBX'; if (!$dryrun) { rhl7FlushResult($ares); } $ares = array(); if (!$procedure_report_id) { if (!$dryrun) { $procedure_report_id = rhl7FlushReport($arep); } $arep = array(); } $ares['procedure_report_id'] = $procedure_report_id; $ares['result_data_type'] = 'E'; $ares['comments'] = $commentdelim; // $fileext = 'pdf'; $filename = date("Ymd_His") . '.' . $fileext; $data = rhl7DecodeData('Base64', $a[2]); if ($data === FALSE) { return rhl7LogMsg(xl('ZEF segment internal error')); } if (!$dryrun) { $d = new Document(); $rc = $d->createDocument($porow['patient_id'], $results_category_id, $filename, rhl7MimeType($fileext), $data); if ($rc) { return rhl7LogMsg($rc); } $ares['document_id'] = $d->get_id(); } $ares['date'] = $arep['date_report']; } else { if ($a[0] == 'NTE' && $context == 'OBX') { $ares['comments'] .= rhl7Text($a[3]) . $commentdelim; } else { return rhl7LogMsg(xl('Segment name') . " '{$a[0]}' " . xl('is misplaced or unknown')); } } } } } } } } } } } if (!$dryrun) { rhl7FlushResult($ares); } // Next line will do something only if there was a report with no results. if (!$dryrun) { rhl7FlushReport($arep); } return $rhl7_return; }
function upload_action_process() { // Collect a manually set owner if this has been set // Used when want to manually assign the owning user/service such as the Direct mechanism $non_HTTP_owner = false; if ($this->manual_set_owner) { $non_HTTP_owner = $this->manual_set_owner; } $couchDB = false; $harddisk = false; if ($GLOBALS['document_storage_method'] == 0) { $harddisk = true; } if ($GLOBALS['document_storage_method'] == 1) { $couchDB = true; } if ($_POST['process'] != "true") { return; } $doDecryption = false; $encrypted = $_POST['encrypted']; $passphrase = $_POST['passphrase']; if (!$GLOBALS['hide_document_encryption'] && $encrypted && $passphrase) { $doDecryption = true; } if (is_numeric($_POST['category_id'])) { $category_id = $_POST['category_id']; } $patient_id = 0; if (isset($_GET['patient_id']) && !$couchDB) { $patient_id = $_GET['patient_id']; } else { if (is_numeric($_POST['patient_id'])) { $patient_id = $_POST['patient_id']; } } $sentUploadStatus = array(); if (count($_FILES['file']['name']) > 0) { $upl_inc = 0; foreach ($_FILES['file']['name'] as $key => $value) { $fname = $value; $err = ""; if ($_FILES['file']['error'][$key] > 0 || empty($fname) || $_FILES['file']['size'][$key] == 0) { $fname = $value; if (empty($fname)) { $fname = htmlentities("<empty>"); } $error = "Error number: " . $_FILES['file']['error'][$key] . " occured while uploading file named: " . $fname . "\n"; if ($_FILES['file']['size'][$key] == 0) { $error .= "The system does not permit uploading files of with size 0.\n"; } } else { $tmpfile = fopen($_FILES['file']['tmp_name'][$key], "r"); $filetext = fread($tmpfile, $_FILES['file']['size'][$key]); fclose($tmpfile); if ($doDecryption) { $filetext = $this->decrypt($filetext, $passphrase); } if ($_POST['destination'] != '') { $fname = $_POST['destination']; } $d = new Document(); $rc = $d->createDocument($patient_id, $category_id, $fname, $_FILES['file']['type'][$key], $filetext, empty($_GET['higher_level_path']) ? '' : $_GET['higher_level_path'], empty($_POST['path_depth']) ? 1 : $_POST['path_depth'], $non_HTTP_owner); if ($rc) { $error .= $rc . "\n"; } else { $this->assign("upload_success", "true"); } $sentUploadStatus[] = $d; $this->assign("file", $sentUploadStatus); } } } $this->assign("error", nl2br($error)); //$this->_state = false; $_POST['process'] = ""; //return $this->fetch($GLOBALS['template_dir'] . "documents/" . $this->template_mod . "_upload.html"); }
/** * Parse and save. * * @param string &$pprow A row from the procedure_providers table. * @param string &$hl7 The input HL7 text. * @return string Error text, or empty if no errors. */ function receive_hl7_results(&$hl7) { if (substr($hl7, 0, 3) != 'MSH') { return xl('Input does not begin with a MSH segment'); } // End-of-line delimiter for text in procedure_result.comments $commentdelim = "\n"; $today = time(); $in_message_id = ''; $in_ssn = ''; $in_dob = ''; $in_lname = ''; $in_fname = ''; $in_orderid = 0; $in_procedure_code = ''; $in_report_status = ''; $in_encounter = 0; $porow = false; $pcrow = false; $procedure_report_id = 0; $arep = array(); // holding area for OBR and its NTE data $ares = array(); // holding area for OBX and its NTE data $code_seq_array = array(); // tracks sequence numbers of order codes // This is so we know where we are if a segment like NTE that can appear in // different places is encountered. $context = ''; // Delimiters $d0 = "\r"; $d1 = substr($hl7, 3, 1); // typically | $d2 = substr($hl7, 4, 1); // typically ^ $d3 = substr($hl7, 5, 1); // typically ~ // We'll need the document category ID for any embedded documents. $catrow = sqlQuery("SELECT id FROM categories WHERE name = ?", array($GLOBALS['lab_results_category_name'])); if (empty($catrow['id'])) { return xl('Document category for lab results does not exist') . ': ' . $GLOBALS['lab_results_category_name']; } $results_category_id = $catrow['id']; $segs = explode($d0, $hl7); foreach ($segs as $seg) { if (empty($seg)) { continue; } $a = explode($d1, $seg); if ($a[0] == 'MSH') { $context = $a[0]; if ($a[8] != 'ORU^R01') { return xl('Message type') . " '{$a[8]}' " . xl('does not seem valid'); } $in_message_id = $a[9]; } else { if ($a[0] == 'PID') { $context = $a[0]; rhl7FlushResult($ares); // Next line will do something only if there was a report with no results. rhl7FlushReport($arep); $in_ssn = $a[4]; $in_dob = $a[7]; // yyyymmdd format $tmp = explode($d2, $a[5]); $in_lname = $tmp[0]; $in_fname = $tmp[1]; } else { if ($a[0] == 'PV1') { // Save placer encounter number if present. if (!empty($a[19])) { $tmp = explode($d2, $a[19]); $in_encounter = intval($tmp[0]); } } else { if ($a[0] == 'ORC') { $context = $a[0]; rhl7FlushResult($ares); // Next line will do something only if there was a report with no results. rhl7FlushReport($arep); $porow = false; $pcrow = false; if ($a[2]) { $in_orderid = intval($a[2]); } } else { if ($a[0] == 'NTE' && $context == 'ORC') { // TBD? Is this ever used? } else { if ($a[0] == 'OBR') { $context = $a[0]; rhl7FlushResult($ares); // Next line will do something only if there was a report with no results. rhl7FlushReport($arep); $procedure_report_id = 0; if ($a[2]) { $in_orderid = intval($a[2]); } $tmp = explode($d2, $a[4]); $in_procedure_code = $tmp[0]; $in_procedure_name = $tmp[1]; $in_report_status = rhl7ReportStatus($a[25]); if (empty($porow)) { $porow = sqlQuery("SELECT * FROM procedure_order WHERE " . "procedure_order_id = ?", array($in_orderid)); // The order must already exist. Currently we do not handle electronic // results returned for manual orders. if (empty($porow)) { return xl('Procedure order') . " '{$in_orderid}' " . xl('was not found'); } if ($in_encounter) { if ($porow['encounter_id'] != $in_encounter) { return xl('Encounter ID') . " '" . $porow['encounter_id'] . "' " . xl('for OBR placer order number') . " '{$in_orderid}' " . xl('does not match the PV1 encounter number') . " '{$in_encounter}'"; } } else { // They did not return an encounter number to verify, so more checking // might be done here to make sure the patient seems to match. } $code_seq_array = array(); } // Find the order line item (procedure code) that matches this result. // If there is more than one, then we select the one whose sequence number // is next after the last sequence number encountered for this procedure // code; this assumes that result OBRs are returned in the same sequence // as the corresponding OBRs in the order. if (!isset($code_seq_array[$in_procedure_code])) { $code_seq_array[$in_procedure_code] = 0; } $pcquery = "SELECT pc.* FROM procedure_order_code AS pc " . "WHERE pc.procedure_order_id = ? AND pc.procedure_code = ? " . "ORDER BY (procedure_order_seq <= ?), procedure_order_seq LIMIT 1"; $pcrow = sqlQuery($pcquery, array($in_orderid, $in_procedure_code, $code_seq_array['$in_procedure_code'])); if (empty($pcrow)) { // There is no matching procedure in the order, so it must have been // added after the original order was sent, either as a manual request // from the physician or as a "reflex" from the lab. // procedure_source = '2' indicates this. sqlInsert("INSERT INTO procedure_order_code SET " . "procedure_order_id = ?, " . "procedure_code = ?, " . "procedure_name = ?, " . "procedure_source = '2'", array($in_orderid, $in_procedure_code, $in_procedure_name)); $pcrow = sqlQuery($pcquery, array($in_orderid, $in_procedure_code)); } $code_seq_array[$in_procedure_code] = 0 + $pcrow['procedure_order_seq']; $arep = array(); $arep['procedure_order_id'] = $in_orderid; $arep['procedure_order_seq'] = $pcrow['procedure_order_seq']; $arep['date_collected'] = rhl7DateTime($a[7]); $arep['date_report'] = substr(rhl7DateTime($a[22]), 0, 10); $arep['report_status'] = $in_report_status; $arep['report_notes'] = ''; } else { if ($a[0] == 'NTE' && $context == 'OBR') { $arep['report_notes'] .= rhl7Text($a[3]) . "\n"; } else { if ($a[0] == 'OBX') { $context = $a[0]; rhl7FlushResult($ares); if (!$procedure_report_id) { $procedure_report_id = rhl7FlushReport($arep); } $ares = array(); $ares['procedure_report_id'] = $procedure_report_id; $ares['result_data_type'] = substr($a[2], 0, 1); // N, S, F or E $ares['comments'] = $commentdelim; if ($a[2] == 'ED') { // This is the case of results as an embedded document. We will create // a normal patient document in the assigned category for lab results. $tmp = explode($d2, $a[5]); $fileext = strtolower($tmp[0]); $filename = date("Ymd_His") . '.' . $fileext; $data = rhl7DecodeData($tmp[3], &$tmp[4]); if ($data === FALSE) { return xl('Invalid encapsulated data encoding type') . ': ' . $tmp[3]; } $d = new Document(); $rc = $d->createDocument($porow['patient_id'], $results_category_id, $filename, rhl7MimeType($fileext), $data); if ($rc) { return $rc; } // This would be error message text. $ares['document_id'] = $d->get_id(); } else { if (strlen($a[5]) > 200) { // OBX-5 can be a very long string of text with "~" as line separators. // The first line of comments is reserved for such things. $ares['result_data_type'] = 'L'; $ares['result'] = ''; $ares['comments'] = rhl7Text($a[5]) . $commentdelim; } else { $ares['result'] = rhl7Text($a[5]); } } $tmp = explode($d2, $a[3]); $ares['result_code'] = rhl7Text($tmp[0]); $ares['result_text'] = rhl7Text($tmp[1]); $ares['date'] = rhl7DateTime($a[14]); $ares['facility'] = rhl7Text($a[15]); $ares['units'] = rhl7Text($a[6]); $ares['range'] = rhl7Text($a[7]); $ares['abnormal'] = rhl7Abnormal($a[8]); // values are lab dependent $ares['result_status'] = rhl7ReportStatus($a[11]); } else { if ($a[0] == 'ZEF') { // ZEF segment is treated like an OBX with an embedded Base64-encoded PDF. $context = 'OBX'; rhl7FlushResult($ares); if (!$procedure_report_id) { $procedure_report_id = rhl7FlushReport($arep); } $ares = array(); $ares['procedure_report_id'] = $procedure_report_id; $ares['result_data_type'] = 'E'; $ares['comments'] = $commentdelim; // $fileext = 'pdf'; $filename = date("Ymd_His") . '.' . $fileext; $data = rhl7DecodeData('Base64', $a[2]); if ($data === FALSE) { return xl('ZEF segment internal error'); } $d = new Document(); $rc = $d->createDocument($porow['patient_id'], $results_category_id, $filename, rhl7MimeType($fileext), $data); if ($rc) { return $rc; } // This would be error message text. $ares['document_id'] = $d->get_id(); // $ares['date'] = $arep['date_report']; } else { if ($a[0] == 'NTE' && $context == 'OBX') { $ares['comments'] .= rhl7Text($a[3]) . $commentdelim; } else { return xl('Segment name') . " '{$a[0]}' " . xl('is misplaced or unknown'); } } } } } } } } } } } rhl7FlushResult($ares); // Next line will do something only if there was a report with no results. rhl7FlushReport($arep); return ''; }