Correction for display of lab results that are long strings of text.
[openemr.git] / interface / orders / single_order_results.inc.php
blob0d40e40ea1fcabb7426ba8b98adce3797251324a
1 <?php
2 /**
3 * Script to display results for a given procedure order.
5 * Copyright (C) 2013-2014 Rod Roark <rod@sunsetsystems.com>
7 * LICENSE: This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>.
18 * @package OpenEMR
19 * @author Rod Roark <rod@sunsetsystems.com>
22 require_once("$srcdir/acl.inc");
23 require_once("$srcdir/formdata.inc.php");
24 require_once("$srcdir/options.inc.php");
25 require_once("$srcdir/formatting.inc.php");
26 require_once("$srcdir/classes/Document.class.php");
28 function getListItem($listid, $value) {
29 $lrow = sqlQuery("SELECT title FROM list_options " .
30 "WHERE list_id = ? AND option_id = ?",
31 array($listid, $value));
32 $tmp = xl_list_label($lrow['title']);
33 if (empty($tmp)) $tmp = (($value === '') ? '' : "($value)");
34 return $tmp;
37 function myCellText($s) {
38 $s = trim($s);
39 if ($s === '') return '&nbsp;';
40 return text($s);
43 // Check if the given string already exists in the $aNotes array.
44 // If not, stores it as a new entry.
45 // Either way, returns the corresponding key which is a small integer.
46 function storeNote($s) {
47 global $aNotes;
48 $key = array_search($s, $aNotes);
49 if ($key !== FALSE) return $key;
50 $key = count($aNotes);
51 $aNotes[$key] = $s;
52 return $key;
55 function generate_order_report($orderid, $input_form=false, $genstyles=true) {
56 global $aNotes;
58 // Check authorization.
59 $thisauth = acl_check('patients', 'med');
60 if (!$thisauth) return xl('Not authorized');
62 $orow = sqlQuery("SELECT " .
63 "po.procedure_order_id, po.date_ordered, po.control_id, " .
64 "po.order_status, po.specimen_type, po.patient_id, " .
65 "pd.pubpid, pd.lname, pd.fname, pd.mname, pd.cmsportal_login, pd.language, " .
66 "fe.date, " .
67 "pp.name AS labname, " .
68 "u.lname AS ulname, u.fname AS ufname, u.mname AS umname " .
69 "FROM procedure_order AS po " .
70 "LEFT JOIN patient_data AS pd ON pd.pid = po.patient_id " .
71 "LEFT JOIN procedure_providers AS pp ON pp.ppid = po.lab_id " .
72 "LEFT JOIN users AS u ON u.id = po.provider_id " .
73 "LEFT JOIN form_encounter AS fe ON fe.pid = po.patient_id AND fe.encounter = po.encounter_id " .
74 "WHERE po.procedure_order_id = ?",
75 array($orderid));
77 $patient_id = $orow['patient_id'];
78 $language = $orow['language'];
81 <?php if ($genstyles) { ?>
82 <style>
83 .labres tr.head { font-size:10pt; background-color:#cccccc; text-align:center; }
84 .labres tr.detail { font-size:10pt; }
85 .labres a, .labres a:visited, .labres a:hover { color:#0000cc; }
86 .labres table {
87 border-style: solid;
88 border-width: 1px 0px 0px 1px;
89 border-color: black;
91 .labres td, .labres th {
92 border-style: solid;
93 border-width: 0px 1px 1px 0px;
94 border-color: black;
96 </style>
97 <?php } ?>
99 <?php if ($input_form) { ?>
100 <script type="text/javascript" src="<?php echo $GLOBALS['webroot']; ?>/library/textformat.js"></script>
101 <?php } // end if input form ?>
103 <?php if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) { ?>
105 <script type="text/javascript" src="<?php echo $GLOBALS['webroot']; ?>/library/dialog.js"></script>
106 <script language="JavaScript">
108 var mypcc = '<?php echo $GLOBALS['phone_country_code'] ?>';
110 // Called to show patient notes related to this order in the "other" frame.
111 // This works even if we are in a separate window.
112 function showpnotes(orderid) {
113 // Find the top or bottom frame that contains or opened this page; return if none.
114 var w = window.opener ? window.opener : window;
115 for (; w.name != 'RTop' && w.name != 'RBot'; w = w.parent) {
116 if (w.parent == w) {
117 // This message is not translated because a developer will need to find it.
118 alert('Internal error locating target frame in ' + (window.opener ? 'opener' : 'window'));
119 return false;
122 var othername = (w.name == 'RTop') ? 'RBot' : 'RTop';
123 w.parent.left_nav.forceDual();
124 w.parent.left_nav.setRadio(othername, 'pno');
125 w.parent.left_nav.loadFrame('pno1', othername, 'patient_file/summary/pnotes_full.php?orderid=' + orderid);
126 return false;
129 // Process click on LOINC code for patient education popup.
130 function educlick(codetype, codevalue) {
131 dlgopen('<?php echo $GLOBALS['webroot']; ?>/interface/patient_file/education.php' +
132 '?type=' + encodeURIComponent(codetype) +
133 '&code=' + encodeURIComponent(codevalue) +
134 '&language=<?php echo urlencode($language); ?>',
135 '_blank', 1024, 750);
138 </script>
140 <?php } // end if not patient report ?>
142 <?php if ($input_form) { ?>
143 <form method='post' action='single_order_results.php?orderid=<?php echo $orderid; ?>'>
144 <?php } // end if input form ?>
146 <div class='labres'>
148 <table width='100%' cellpadding='2' cellspacing='0'>
149 <tr bgcolor='#cccccc'>
150 <td width='5%' nowrap><?php echo xlt('Patient ID'); ?></td>
151 <td width='45%'><?php echo myCellText($orow['pubpid']); ?></td>
152 <td width='5%' nowrap><?php echo xlt('Order ID'); ?></td>
153 <td width='45%'>
154 <?php
155 if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) {
156 echo " <a href='" . $GLOBALS['webroot'];
157 echo "/interface/orders/order_manifest.php?orderid=";
158 echo attr($orow['procedure_order_id']);
159 echo "' target='_blank' onclick='top.restoreSession()'>";
161 echo myCellText($orow['procedure_order_id']);
162 if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) {
163 echo "</a>\n";
165 if ($orow['control_id']) {
166 echo myCellText(' ' . xl('Lab') . ': ' . $orow['control_id']);
169 </td>
170 </tr>
171 <tr bgcolor='#cccccc'>
172 <td nowrap><?php echo xlt('Patient Name'); ?></td>
173 <td><?php echo myCellText($orow['lname'] . ', ' . $orow['fname'] . ' ' . $orow['mname']); ?></td>
174 <td nowrap><?php echo xlt('Ordered By'); ?></td>
175 <td><?php echo myCellText($orow['ulname'] . ', ' . $orow['ufname'] . ' ' . $orow['umname']); ?></td>
176 </tr>
177 <tr bgcolor='#cccccc'>
178 <td nowrap><?php echo xlt('Order Date'); ?></td>
179 <td><?php echo myCellText(oeFormatShortDate($orow['date_ordered'])); ?></td>
180 <td nowrap><?php echo xlt('Print Date'); ?></td>
181 <td><?php echo oeFormatShortDate(date('Y-m-d')); ?></td>
182 </tr>
183 <tr bgcolor='#cccccc'>
184 <td nowrap><?php echo xlt('Order Status'); ?></td>
185 <td><?php echo myCellText($orow['order_status']); ?></td>
186 <td nowrap><?php echo xlt('Encounter Date'); ?></td>
187 <td><?php echo myCellText(oeFormatShortDate(substr($orow['date'], 0, 10))); ?></td>
188 </tr>
189 <tr bgcolor='#cccccc'>
190 <td nowrap><?php echo xlt('Lab'); ?></td>
191 <td><?php echo myCellText($orow['labname']); ?></td>
192 <td nowrap><?php echo xlt('Specimen Type'); ?></td>
193 <td><?php echo myCellText($orow['specimen_type']); ?></td>
194 </tr>
195 </table>
197 &nbsp;<br />
199 <table width='100%' cellpadding='2' cellspacing='0'>
201 <tr class='head'>
202 <td rowspan='2' valign='middle'><?php echo xlt('Ordered Procedure'); ?></td>
203 <td colspan='4'><?php echo xlt('Report'); ?></td>
204 <td colspan='7'><?php echo xlt('Results'); ?></td>
205 </tr>
207 <tr class='head'>
208 <td><?php echo xlt('Reported'); ?></td>
209 <td><?php echo xlt('Specimen'); ?></td>
210 <td><?php echo xlt('Status'); ?></td>
211 <td><?php echo xlt('Note'); ?></td>
212 <td><?php echo xlt('Code'); ?></td>
213 <td><?php echo xlt('Name'); ?></td>
214 <td><?php echo xlt('Abn'); ?></td>
215 <td><?php echo xlt('Value'); ?></td>
216 <td><?php echo xlt('Range'); ?></td>
217 <td><?php echo xlt('Units'); ?></td>
218 <td><?php echo xlt('Note'); ?></td>
219 </tr>
221 <?php
222 $query = "SELECT " .
223 "po.lab_id, po.date_ordered, pc.procedure_order_seq, pc.procedure_code, " .
224 "pc.procedure_name, " .
225 "pr.procedure_report_id, pr.date_report, pr.date_collected, pr.specimen_num, " .
226 "pr.report_status, pr.review_status, pr.report_notes " .
227 "FROM procedure_order AS po " .
228 "JOIN procedure_order_code AS pc ON pc.procedure_order_id = po.procedure_order_id " .
229 "LEFT JOIN procedure_report AS pr ON pr.procedure_order_id = po.procedure_order_id AND " .
230 "pr.procedure_order_seq = pc.procedure_order_seq " .
231 "WHERE po.procedure_order_id = ? " .
232 "ORDER BY pc.procedure_order_seq, pr.procedure_report_id";
234 $res = sqlStatement($query, array($orderid));
236 $lastpoid = -1;
237 $lastpcid = -1;
238 $lastprid = -1;
239 $encount = 0;
240 $lino = 0;
241 $extra_html = '';
242 $aNotes = array();
243 $sign_list = '';
245 while ($row = sqlFetchArray($res)) {
246 $lab_id = empty($row['lab_id' ]) ? 0 : ($row['lab_id' ] + 0);
247 $order_type_id = empty($row['order_type_id' ]) ? 0 : ($row['order_type_id' ] + 0);
248 $order_seq = empty($row['procedure_order_seq']) ? 0 : ($row['procedure_order_seq'] + 0);
249 $report_id = empty($row['procedure_report_id']) ? 0 : ($row['procedure_report_id'] + 0);
250 $procedure_code = empty($row['procedure_code' ]) ? '' : $row['procedure_code'];
251 $procedure_name = empty($row['procedure_name' ]) ? '' : $row['procedure_name'];
252 $date_report = empty($row['date_report' ]) ? '' : $row['date_report'];
253 $date_collected = empty($row['date_collected' ]) ? '' : substr($row['date_collected'], 0, 16);
254 $specimen_num = empty($row['specimen_num' ]) ? '' : $row['specimen_num'];
255 $report_status = empty($row['report_status' ]) ? '' : $row['report_status'];
256 $review_status = empty($row['review_status' ]) ? 'received' : $row['review_status'];
258 if ($review_status != 'reviewed' && $report_id) {
259 if ($sign_list) $sign_list .= ',';
260 $sign_list .= $report_id;
263 $report_noteid ='';
264 if (!empty($row['report_notes'])) {
265 $report_noteid = 1 + storeNote($row['report_notes']);
268 $query = "SELECT " .
269 "ps.result_code, ps.result_text, ps.abnormal, ps.result, ps.range, " .
270 "ps.result_status, ps.facility, ps.units, ps.comments, ps.document_id " .
271 "FROM procedure_result AS ps " .
272 "WHERE ps.procedure_report_id = ? " .
273 "ORDER BY ps.result_code, ps.procedure_result_id";
275 $rres = sqlStatement($query, array($report_id));
276 $rrows = array();
277 while ($rrow = sqlFetchArray($rres)) {
278 $rrows[] = $rrow;
280 if (empty($rrows)) {
281 $rrows[0] = array('result_code' => '');
284 foreach ($rrows as $rrow) {
285 $result_code = empty($rrow['result_code' ]) ? '' : $rrow['result_code'];
286 $result_text = empty($rrow['result_text' ]) ? '' : $rrow['result_text'];
287 $result_abnormal = empty($rrow['abnormal' ]) ? '' : $rrow['abnormal'];
288 $result_result = empty($rrow['result' ]) ? '' : $rrow['result'];
289 $result_units = empty($rrow['units' ]) ? '' : $rrow['units'];
290 $result_facility = empty($rrow['facility' ]) ? '' : $rrow['facility'];
291 $result_comments = empty($rrow['comments' ]) ? '' : $rrow['comments'];
292 $result_range = empty($rrow['range' ]) ? '' : $rrow['range'];
293 $result_status = empty($rrow['result_status' ]) ? '' : $rrow['result_status'];
294 $result_document_id = empty($rrow['document_id' ]) ? '' : $rrow['document_id'];
296 if ($i = strpos($result_comments, "\n")) { // "=" is not a mistake!
297 // If the first line of comments is not empty, then it is actually a long textual
298 // result value with lines delimited by "~" characters.
299 $result_comments = str_replace("~", "\n", substr($result_comments, 0, $i)) .
300 substr($result_comments, $i);
302 $result_comments = trim($result_comments);
304 $result_noteid = '';
305 if (!empty($result_comments)) {
306 $result_noteid = 1 + storeNote($result_comments);
309 if ($lastpoid != $order_id || $lastpcid != $order_seq) {
310 ++$encount;
312 $bgcolor = "#" . (($encount & 1) ? "ddddff" : "ffdddd");
314 echo " <tr class='detail' bgcolor='$bgcolor'>\n";
316 if ($lastpcid != $order_seq) {
317 $lastprid = -1; // force report fields on first line of each procedure
318 $tmp = text("$procedure_code: $procedure_name");
319 // Get the LOINC code if one exists in the compendium for this order type.
320 if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) {
321 $trow = sqlQuery("SELECT standard_code FROM procedure_type WHERE " .
322 "lab_id = ? AND procedure_code = ? AND procedure_type = 'ord' " .
323 "ORDER BY procedure_type_id LIMIT 1",
324 array($lab_id, $procedure_code));
325 if (!empty($trow['standard_code'])) {
326 $tmp = "<a href='javascript:educlick(\"LOINC\",\"" . attr($trow['standard_code']) .
327 "\")'>$tmp</a>";
330 echo " <td>$tmp</td>\n";
332 else {
333 echo " <td style='background-color:transparent'>&nbsp;</td>";
336 // If this starts a new report or a new order, generate the report fields.
337 if ($report_id != $lastprid) {
338 echo " <td>";
339 echo myCellText(oeFormatShortDate($date_report));
340 echo "</td>\n";
342 echo " <td>";
343 echo myCellText($specimen_num);
344 echo "</td>\n";
346 echo " <td title='" . xla('Check mark indicates reviewed') . "'>";
347 echo myCellText(getListItem('proc_rep_status', $report_status));
348 if ($row['review_status'] == 'reviewed') {
349 echo " &#x2713;"; // unicode check mark character
351 echo "</td>\n";
353 echo " <td align='center'>";
354 echo myCellText($report_noteid);
355 echo "</td>\n";
357 else {
358 echo " <td colspan='4' style='background-color:transparent'>&nbsp;</td>\n";
361 if ($result_code !== '' || $result_document_id) {
362 $tmp = myCellText($result_code);
363 if (empty($GLOBALS['PATIENT_REPORT_ACTIVE']) && !empty($result_code)) {
364 $tmp = "<a href='javascript:educlick(\"LOINC\",\"" . attr($result_code) .
365 "\")'>$tmp</a>";
367 echo " <td>$tmp</td>\n";
368 echo " <td>";
369 echo myCellText($result_text);
370 echo "</td>\n";
371 echo " <td>";
372 echo myCellText(getListItem('proc_res_abnormal', $result_abnormal));
373 echo "</td>\n";
375 if ($result_document_id) {
376 $d = new Document($result_document_id);
377 echo " <td colspan='3'>";
378 if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) {
379 echo "<a href='" . $GLOBALS['webroot'] . "/controller.php?document";
380 echo "&retrieve&patient_id=$patient_id&document_id=$result_document_id' ";
381 echo "onclick='top.restoreSession()'>";
383 echo $d->get_url_file();
384 if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) {
385 echo "</a>";
387 echo "</td>\n";
389 else {
390 echo " <td>";
391 echo myCellText($result_result);
392 echo "</td>\n";
393 echo " <td>";
394 echo myCellText($result_range);
395 echo "</td>\n";
396 echo " <td>";
397 echo myCellText($result_units);
398 echo "</td>\n";
400 echo " <td align='center'>";
401 echo myCellText($result_noteid);
402 echo "</td>\n";
404 else {
405 echo " <td colspan='7' style='background-color:transparent'>&nbsp;</td>\n";
408 echo " </tr>\n";
410 $lastpoid = $order_id;
411 $lastpcid = $order_seq;
412 $lastprid = $report_id;
413 ++$lino;
418 </table>
420 &nbsp;<br />
421 <table width='100%' style='border-width:0px;'>
422 <tr>
423 <td style='border-width:0px;'>
424 <?php
425 if (!empty($aNotes)) {
426 echo "<table cellpadding='3' cellspacing='0'>\n";
427 echo " <tr bgcolor='#cccccc'>\n";
428 echo " <th align='center' colspan='2'>" . xlt('Notes') . "</th>\n";
429 echo " </tr>\n";
430 foreach ($aNotes as $key => $value) {
431 echo " <tr>\n";
432 echo " <td valign='top'>" . ($key + 1) . "</td>\n";
433 echo " <td>" . nl2br(text($value)) . "</td>\n";
434 echo " </tr>\n";
436 echo "</table>\n";
439 </td>
440 <td style='border-width:0px;' align='right' valign='top'>
441 <?php if (empty($GLOBALS['PATIENT_REPORT_ACTIVE'])) { ?>
442 <input type='button' value='<?php echo xla('Related Patient Notes'); ?>'
443 onclick='showpnotes(<?php echo $orderid; ?>)' />
444 <?php } ?>
445 <?php if ($input_form && $sign_list) { ?>
446 &nbsp;
447 <input type='hidden' name='form_sign_list' value='<?php echo attr($sign_list); ?>' />
448 <input type='submit' name='form_sign' value='<?php echo xla('Sign Results'); ?>'
449 title='<?php echo xla('Mark these reports as reviewed'); ?>' />
450 <?php
451 // If this is a portal patient, sending them a copy is an option.
452 if ($GLOBALS['gbl_portal_cms_enable'] && $orow['cmsportal_login'] !== '') {
453 echo "&nbsp;";
454 echo "<input type='checkbox' name='form_send_to_portal' value='" .
455 attr($orow['cmsportal_login']) . "' checked />\n";
456 echo xlt('Send to portal');
459 <?php } ?>
460 <?php if ($input_form) { ?>
461 &nbsp;
462 <input type='button' value='<?php echo xla('Close'); ?>' onclick='window.close()' />
463 <?php } ?>
464 </td>
465 </tr>
466 </table>
468 </div>
470 <?php if ($input_form) { ?>
471 </form>
472 <?php } // end if input form ?>
474 <?php
475 } // end function generate_order_report