added support for mariadb in the ubuntu-debian packages
[openemr.git] / interface / forms / procedure_order / new.php
blobbb5c6123ca54af0eeadeb81446deb4b0916b8332
1 <?php
2 /**
3 * Encounter form for entering procedure orders.
5 * Copyright (C) 2010-2013 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("../../globals.php");
23 require_once("$srcdir/api.inc");
24 require_once("$srcdir/forms.inc");
25 require_once("$srcdir/options.inc.php");
26 require_once("$srcdir/formdata.inc.php");
27 require_once("$srcdir/formatting.inc.php");
28 require_once("../../orders/qoe.inc.php");
29 require_once("../../orders/gen_hl7_order.inc.php");
30 require_once("../../../custom/code_types.inc.php");
32 // Defaults for new orders.
33 $row = array(
34 'provider_id' => $_SESSION['authUserID'],
35 'date_ordered' => date('Y-m-d'),
36 'date_collected' => date('Y-m-d H:i'),
39 if (! $encounter) { // comes from globals.php
40 die("Internal error: we do not seem to be in an encounter!");
43 function cbvalue($cbname) {
44 return $_POST[$cbname] ? '1' : '0';
47 function cbinput($name, $colname) {
48 global $row;
49 $ret = "<input type='checkbox' name='$name' value='1'";
50 if ($row[$colname]) $ret .= " checked";
51 $ret .= " />";
52 return $ret;
55 function cbcell($name, $desc, $colname) {
56 return "<td width='25%' nowrap>" . cbinput($name, $colname) . "$desc</td>\n";
59 function QuotedOrNull($fld) {
60 if (empty($fld)) return "NULL";
61 return "'$fld'";
64 function getListOptions($list_id , $fieldnames=array('option_id', 'title', 'seq'))
66 $output = array();
67 $query = sqlStatement("SELECT ".implode(',',$fieldnames)." FROM list_options where list_id=? order by seq", array($list_id));
68 while($ll = sqlFetchArray($query)) {
69 foreach($fieldnames as $val)
70 $output[$ll['option_id']][$val] = $ll[$val];
72 return $output;
74 $formid = formData('id', 'G') + 0;
76 // If Save or Transmit was clicked, save the info.
78 if ($_POST['bn_save'] || $_POST['bn_xmit']) {
79 $ppid = formData('form_lab_id') + 0;
81 $sets =
82 "date_ordered = " . QuotedOrNull(formData('form_date_ordered')) . ", " .
83 "provider_id = " . (formData('form_provider_id') + 0) . ", " .
84 "lab_id = " . $ppid . ", " .
85 "date_collected = " . QuotedOrNull(formData('form_date_collected')) . ", " .
86 "order_priority = '" . formData('form_order_priority') . "', " .
87 "order_status = '" . formData('form_order_status') . "', " .
88 "clinical_hx = '" . formData('form_clinical_hx') . "', " .
89 "patient_instructions = '" . formData('form_patient_instructions') . "', " .
90 "patient_id = '" . $pid . "', " .
91 "encounter_id = '" . $encounter . "'";
93 // If updating an existing form...
95 if ($formid) {
96 $query = "UPDATE procedure_order SET $sets " .
97 "WHERE procedure_order_id = '$formid'";
98 sqlStatement($query);
101 // If adding a new form...
103 else {
104 $query = "INSERT INTO procedure_order SET $sets";
105 $formid = sqlInsert($query);
106 addForm($encounter, "Procedure Order", $formid, "procedure_order", $pid, $userauthorized);
109 // Remove any existing procedures and their answers for this order and
110 // replace them from the form.
112 sqlStatement("DELETE FROM procedure_answers WHERE procedure_order_id = ?",
113 array($formid));
114 sqlStatement("DELETE FROM procedure_order_code WHERE procedure_order_id = ?",
115 array($formid));
117 for ($i = 0; isset($_POST['form_proc_type'][$i]); ++$i) {
118 $ptid = $_POST['form_proc_type'][$i] + 0;
119 if ($ptid <= 0) continue;
121 $prefix = "ans$i" . "_";
123 $poseq = sqlInsert("INSERT INTO procedure_order_code SET ".
124 "procedure_order_id = ?, " .
125 "diagnoses = ?, " .
126 "procedure_order_title = ?, " .
127 "procedure_code = (SELECT procedure_code FROM procedure_type WHERE procedure_type_id = ?), " .
128 "procedure_name = (SELECT name FROM procedure_type WHERE procedure_type_id = ?)",
129 array($formid, strip_escape_custom($_POST['form_proc_type_diag'][$i]), strip_escape_custom($_POST['form_proc_order_title'][$i]), $ptid, $ptid));
131 $qres = sqlStatement("SELECT " .
132 "q.procedure_code, q.question_code, q.options, q.fldtype " .
133 "FROM procedure_type AS t " .
134 "JOIN procedure_questions AS q ON q.lab_id = t.lab_id " .
135 "AND q.procedure_code = t.procedure_code AND q.activity = 1 " .
136 "WHERE t.procedure_type_id = ? " .
137 "ORDER BY q.seq, q.question_text", array($ptid));
139 while ($qrow = sqlFetchArray($qres)) {
140 $options = trim($qrow['options']);
141 $qcode = trim($qrow['question_code']);
142 $fldtype = $qrow['fldtype'];
143 $data = '';
144 if ($fldtype == 'G') {
145 if ($_POST["G1_$prefix$qcode"]) {
146 $data = $_POST["G1_$prefix$qcode"] * 7 + $_POST["G2_$prefix$qcode"];
149 else {
150 $data = $_POST["$prefix$qcode"];
152 if (!isset($data) || $data === '') continue;
153 if (!is_array($data)) $data = array($data);
154 foreach ($data as $datum) {
155 // Note this will auto-assign the seq value.
156 sqlStatement("INSERT INTO procedure_answers SET ".
157 "procedure_order_id = ?, " .
158 "procedure_order_seq = ?, " .
159 "question_code = ?, " .
160 "answer = ?",
161 array($formid, $poseq, $qcode, strip_escape_custom($datum)));
166 $alertmsg = '';
167 if ($_POST['bn_xmit']) {
168 $hl7 = '';
169 $alertmsg = gen_hl7_order($formid, $hl7);
170 if (empty($alertmsg)) {
171 $alertmsg = send_hl7_order($ppid, $hl7);
173 if (empty($alertmsg)) {
174 sqlStatement("UPDATE procedure_order SET date_transmitted = NOW() WHERE " .
175 "procedure_order_id = ?", array($formid));
179 formHeader("Redirecting....");
180 if ($alertmsg) {
181 echo "\n<script language='Javascript'>alert('";
182 echo addslashes(xl('Transmit failed') . ': ' . $alertmsg);
183 echo "')</script>\n";
185 formJump();
186 formFooter();
187 exit;
190 if ($formid) {
191 $row = sqlQuery ("SELECT * FROM procedure_order WHERE " .
192 "procedure_order_id = ?",
193 array($formid)) ;
196 $enrow = sqlQuery("SELECT p.fname, p.mname, p.lname, fe.date FROM " .
197 "form_encounter AS fe, forms AS f, patient_data AS p WHERE " .
198 "p.pid = ? AND f.pid = p.pid AND f.encounter = ? AND " .
199 "f.formdir = 'newpatient' AND f.deleted = 0 AND " .
200 "fe.id = f.form_id LIMIT 1",
201 array($pid, $encounter));
203 <html>
204 <head>
205 <?php html_header_show(); ?>
206 <link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css" />
208 <style>
210 td {
211 font-size:10pt;
214 .inputtext {
215 padding-left:2px;
216 padding-right:2px;
219 </style>
221 <style type="text/css">@import url(<?php echo $GLOBALS['webroot'] ?>/library/dynarch_calendar.css);</style>
222 <script type="text/javascript" src="<?php echo $GLOBALS['webroot'] ?>/library/dynarch_calendar.js"></script>
223 <?php include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?>
224 <script type="text/javascript" src="<?php echo $GLOBALS['webroot'] ?>/library/dynarch_calendar_setup.js"></script>
226 <script type="text/javascript" src="../../../library/dialog.js"></script>
227 <script type="text/javascript" src="<?php echo $GLOBALS['webroot'] ?>/library/textformat.js"></script>
229 <script language='JavaScript'>
231 // This invokes the find-procedure-type popup.
232 // formseq = 0-relative index in the form.
233 var gbl_formseq;
234 function sel_proc_type(formseq) {
235 var f = document.forms[0];
236 // if (!f.form_lab_id.value) {
237 // alert('<?php echo xls('Please select a procedure provider'); ?>');
238 // return;
239 // }
240 gbl_formseq = formseq;
241 var ptvarname = 'form_proc_type[' + formseq + ']';
242 /********************************************************************
243 dlgopen('../../orders/types.php?popup=1' +
244 '&labid=' + f.form_lab_id.value +
245 '&order=' + f[ptvarname].value +
246 '&formid=<?php echo $formid; ?>' +
247 '&formseq=' + formseq,
248 '_blank', 800, 500);
249 ********************************************************************/
250 // This replaces the above for an easier/faster order picker tool.
251 dlgopen('../../orders/find_order_popup.php' +
252 '?labid=' + f.form_lab_id.value +
253 '&order=' + f[ptvarname].value +
254 '&formid=<?php echo $formid; ?>' +
255 '&formseq=' + formseq,
256 '_blank', 800, 500);
259 // This is for callback by the find-procedure-type popup.
260 // Sets both the selected type ID and its descriptive name.
261 function set_proc_type(typeid, typename) {
262 var f = document.forms[0];
263 var ptvarname = 'form_proc_type[' + gbl_formseq + ']';
264 var ptdescname = 'form_proc_type_desc[' + gbl_formseq + ']';
265 f[ptvarname].value = typeid;
266 f[ptdescname].value = typename;
269 // This is also for callback by the find-procedure-type popup.
270 // Sets the contents of the table containing the form fields for questions.
271 function set_proc_html(s, js) {
272 document.getElementById('qoetable[' + gbl_formseq + ']').innerHTML = s;
273 eval(js);
276 // New lab selected so clear all procedures and questions from the form.
277 function lab_id_changed() {
278 var f = document.forms[0];
279 for (var i = 0; true; ++i) {
280 var ix = '[' + i + ']';
281 if (!f['form_proc_type' + ix]) break;
282 f['form_proc_type' + ix].value = '-1';
283 f['form_proc_type_desc' + ix].value = '';
284 document.getElementById('qoetable' + ix).innerHTML = '';
288 // Add a line for entry of another procedure.
289 function addProcLine() {
290 var f = document.forms[0];
291 var table = document.getElementById('proctable');
292 var e = document.getElementById("procedure_type_names");
293 var prc_name = e.options[e.selectedIndex].value;
294 // Compute i = next procedure index.
295 var i = 0;
296 for (; f['form_proc_type[' + i + ']']; ++i);
297 var row = table.insertRow(table.rows.length);
298 var cell = row.insertCell(0);
299 cell.vAlign = 'top';
300 //cell.innerHTML = "<b><?php echo xl('Procedure'); ?> " + (i + 1) + ":</b>";
301 cell.innerHTML = "<b>"+prc_name+"<input type='hidden' name='form_proc_order_title[" + i + "]' value='"+ prc_name +"'></b>";
302 var cell = row.insertCell(1);
303 cell.vAlign = 'top';
304 cell.innerHTML =
305 "<input type='text' size='50' name='form_proc_type_desc[" + i + "]'" +
306 " onclick='sel_proc_type(" + i + ")'" +
307 " onfocus='this.blur()'" +
308 " title='<?php echo xla('Click to select the desired procedure'); ?>'" +
309 " style='width:100%;cursor:pointer;cursor:hand' readonly />" +
310 " <input type='hidden' name='form_proc_type[" + i + "]' value='-1' />" +
311 "<br /><?php echo xla('Diagnosis Codes'); ?>: " +
312 "<input type='text' size='50' name='form_proc_type_diag[" + i + "]'" +
313 " onclick='sel_related(this.name)'" +
314 " title='<?php echo xla('Click to add a diagnosis'); ?>'" +
315 " onfocus='this.blur()'" +
316 " style='cursor:pointer;cursor:hand' readonly />" +
317 " <div style='width:95%;' id='qoetable[" + i + "]'></div>";
318 sel_proc_type(i);
319 return false;
322 // The name of the form field for find-code popup results.
323 var rcvarname;
325 // This is for callback by the find-code popup.
326 // Appends to or erases the current list of related codes.
327 function set_related(codetype, code, selector, codedesc) {
328 var f = document.forms[0];
329 var s = f[rcvarname].value;
330 if (code) {
331 if (s.length > 0) s += ';';
332 s += codetype + ':' + code;
333 } else {
334 s = '';
336 f[rcvarname].value = s;
339 // This invokes the find-code popup.
340 function sel_related(varname) {
341 rcvarname = varname;
342 // codetype is just to make things easier and avoid mistakes.
343 // Might be nice to have a lab parameter for acceptable code types.
344 // Also note the controlling script here runs from interface/patient_file/encounter/.
345 dlgopen('find_code_popup.php?codetype=<?php echo attr(collect_codetypes("diagnosis","csv")) ?>', '_blank', 500, 400);
348 var transmitting = false;
350 // Issue a Cancel/OK warning if a previously transmitted order is being transmitted again.
351 function validate(f) {
352 <?php if (!empty($row['date_transmitted'])) { ?>
353 if (transmitting) {
354 if (!confirm('<?php echo xls('This order was already transmitted on') . ' ' .
355 addslashes($row['date_transmitted']) . '. ' .
356 xls('Are you sure you want to transmit it again?'); ?>')) {
357 return false;
360 <?php } ?>
361 top.restoreSession();
362 return true;
365 </script>
367 </head>
369 <body class="body_top">
371 <form method="post" action="<?php echo $rootdir ?>/forms/procedure_order/new.php?id=<?php echo $formid ?>"
372 onsubmit="return validate(this)">
374 <p class='title' style='margin-top:8px;margin-bottom:8px;text-align:center'>
375 <?php
376 echo xl('Procedure Order for') . ' ';
377 echo $enrow['fname'] . ' ' . $enrow['mname'] . ' ' . $enrow['lname'];
378 echo ' ' . xl('on') . ' ' . oeFormatShortDate(substr($enrow['date'], 0, 10));
380 </p>
382 <center>
385 <table border='1' width='95%' id='proctable'>
387 <tr>
388 <td width='1%' valign='top' nowrap><b><?php xl('Ordering Provider','e'); ?>:</b></td>
389 <td valign='top'>
390 <?php
391 generate_form_field(array('data_type'=>10,'field_id'=>'provider_id'),
392 $row['provider_id']);
394 </td>
395 </tr>
397 <tr>
398 <td width='1%' valign='top' nowrap><b><?php xl('Sending To','e'); ?>:</b></td>
399 <td valign='top'>
400 <select name='form_lab_id' onchange='lab_id_changed()'>
401 <?php
402 $ppres = sqlStatement("SELECT ppid, name FROM procedure_providers " .
403 "ORDER BY name, ppid");
404 while ($pprow = sqlFetchArray($ppres)) {
405 echo "<option value='" . attr($pprow['ppid']) . "'";
406 if ($pprow['ppid'] == $row['lab_id']) echo " selected";
407 echo ">" . text($pprow['name']) . "</option>";
410 </select>
411 </td>
412 </tr>
414 <tr>
415 <td width='1%' valign='top' nowrap><b><?php xl('Order Date','e'); ?>:</b></td>
416 <td valign='top'>
417 <?php
418 echo "<input type='text' size='10' name='form_date_ordered' id='form_date_ordered'" .
419 " value='" . $row['date_ordered'] . "'" .
420 " title='" . xl('Date of this order') . "'" .
421 " onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)'" .
422 " />" .
423 "<img src='$rootdir/pic/show_calendar.gif' align='absbottom' width='24' height='22'" .
424 " id='img_date_ordered' border='0' alt='[?]' style='cursor:pointer'" .
425 " title='" . xl('Click here to choose a date') . "' />";
427 </td>
428 </tr>
430 <tr>
431 <td width='1%' valign='top' nowrap><b><?php xl('Internal Time Collected','e'); ?>:</b></td>
432 <td valign='top'>
433 <?php
434 echo "<input type='text' size='16' name='form_date_collected' id='form_date_collected'" .
435 " value='" . substr($row['date_collected'], 0, 16) . "'" .
436 " title='" . xl('Date and time that the sample was collected') . "'" .
437 // " onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)'" .
438 " />" .
439 "<img src='$rootdir/pic/show_calendar.gif' align='absbottom' width='24' height='22'" .
440 " id='img_date_collected' border='0' alt='[?]' style='cursor:pointer'" .
441 " title='" . xl('Click here to choose a date and time') . "' />";
443 </td>
444 </tr>
446 <tr>
447 <td width='1%' valign='top' nowrap><b><?php xl('Priority','e'); ?>:</b></td>
448 <td valign='top'>
449 <?php
450 generate_form_field(array('data_type'=>1,'field_id'=>'order_priority',
451 'list_id'=>'ord_priority'), $row['order_priority']);
453 </td>
454 </tr>
456 <tr>
457 <td width='1%' valign='top' nowrap><b><?php xl('Status','e'); ?>:</b></td>
458 <td valign='top'>
459 <?php
460 generate_form_field(array('data_type'=>1,'field_id'=>'order_status',
461 'list_id'=>'ord_status'), $row['order_status']);
463 </td>
464 </tr>
466 <tr>
467 <td width='1%' valign='top' nowrap><b><?php xl('Clinical History','e'); ?>:</b></td>
468 <td valign='top'>
469 <input type='text' maxlength='255' name='form_clinical_hx' style='width:100%'
470 class='inputtext' value='<?php echo attr($row['clinical_hx']); ?>' />
471 </td>
472 </tr>
474 <!-- Will enable this later, nothing uses it yet. -->
475 <tr style='display:none'>
476 <td width='1%' valign='top' nowrap><b><?php xl('Patient Instructions','e'); ?>:</b></td>
477 <td valign='top'>
478 <textarea rows='3' cols='40' name='form_patient_instructions' style='width:100%'
479 wrap='virtual' class='inputtext' /><?php echo $row['patient_instructions'] ?></textarea>
480 </td>
481 </tr>
483 <?php
485 // This section merits some explanation. :)
487 // If any procedures have already been saved for this form, then a top-level table row is
488 // created for each of them, and includes the relevant questions and any existing answers.
489 // Otherwise a single empty table row is created for entering the first or only procedure.
491 // If a new procedure is selected or changed, the questions for it are (re)generated from
492 // the dialog window from which the procedure is selected, via JavaScript. The sel_proc_type
493 // function and the types.php script that it invokes collaborate to support this feature.
495 // The generate_qoe_html function in qoe.inc.php contains logic to generate the HTML for
496 // the questions, and can be invoked either from this script or from types.php.
498 // The $i counter that you see below is to resolve the need for unique names for form fields
499 // that may occur for each of the multiple procedure requests within the same order.
500 // procedure_order_seq serves a similar need for uniqueness at the database level.
502 $oparr = array();
503 if ($formid) {
504 $opres = sqlStatement("SELECT " .
505 "pc.procedure_order_seq, pc.procedure_code, pc.procedure_name, " .
506 "pc.diagnoses,pc.procedure_order_title, pt.procedure_type_id " .
507 "FROM procedure_order_code AS pc " .
508 "LEFT JOIN procedure_type AS pt ON pt.lab_id = ? AND " .
509 "pt.procedure_code = pc.procedure_code " .
510 "WHERE pc.procedure_order_id = ? " .
511 "ORDER BY pc.procedure_order_seq",
512 array($row['lab_id'], $formid));
513 while ($oprow = sqlFetchArray($opres)) {
514 $oparr[] = $oprow;
517 if (empty($oparr)) $oparr[] = array('procedure_name' => '');
519 $i = 0;
520 foreach ($oparr as $oprow) {
521 $ptid = -1; // -1 means no procedure is selected yet
522 if (!empty($oprow['procedure_type_id'])) {
523 $ptid = $oprow['procedure_type_id'];
526 <tr>
527 <!--<td width='1%' valign='top'><b><?php echo xl('Procedure') . ' ' . ($i + 1); ?>:</b></td>-->
528 <?php if(empty($formid) || empty($oprow['procedure_order_title'])) {?>
529 <td width='1%' valign='top'><input type='hidden' name='form_proc_order_title[<?php echo $i; ?>]' value='Procedure'><b><?php echo xlt('Procedure');?></b></td>
530 <?php } else {?>
531 <td width='1%' valign='top'>
532 <input type='hidden' name='form_proc_order_title[<?php echo $i; ?>]' value='<?php echo attr($oprow['procedure_order_title']) ?>'><b><?php echo text($oprow['procedure_order_title']) ?></b>
533 </td>
534 <?php } ?>
535 <td valign='top'>
536 <input type='text' size='50' name='form_proc_type_desc[<?php echo $i; ?>]'
537 value='<?php echo attr($oprow['procedure_name']) ?>'
538 onclick="sel_proc_type(<?php echo $i; ?>)"
539 onfocus='this.blur()'
540 title='<?php xla('Click to select the desired procedure','e'); ?>'
541 style='width:100%;cursor:pointer;cursor:hand' readonly />
542 <input type='hidden' name='form_proc_type[<?php echo $i; ?>]' value='<?php echo $ptid ?>' />
543 <br /><?php echo xlt('Diagnosis Codes'); ?>:
544 <input type='text' size='50' name='form_proc_type_diag[<?php echo $i; ?>]'
545 value='<?php echo attr($oprow['diagnoses']) ?>' onclick='sel_related(this.name)'
546 title='<?php echo xla('Click to add a diagnosis'); ?>'
547 onfocus='this.blur()'
548 style='cursor:pointer;cursor:hand' readonly />
549 <!-- MSIE innerHTML property for a TABLE element is read-only, so using a DIV here. -->
550 <div style='width:95%;' id='qoetable[<?php echo $i; ?>]'>
551 <?php
552 $qoe_init_javascript = '';
553 echo generate_qoe_html($ptid, $formid, $oprow['procedure_order_seq'], $i);
554 if ($qoe_init_javascript)
555 echo "<script language='JavaScript'>$qoe_init_javascript</script>";
557 </div>
558 </td>
559 </tr>
560 <?php
561 ++$i;
565 </table>
568 <?php $procedure_order_type = getListOptions('order_type' , array('option_id', 'title')); ?>
569 <select name="procedure_type_names" id="procedure_type_names">
570 <?php foreach($procedure_order_type as $ordered_types){?>
571 <option value="<?php echo attr($ordered_types['option_id']); ?>" ><?php echo text(xl_list_label($ordered_types['title'])) ; ?></option>
572 <?php } ?>
573 </select>
574 <input type='button' value='<?php echo xla('Add Procedure'); ?>' onclick="addProcLine()" />
575 &nbsp;
576 <input type='submit' name='bn_save' value='<?php echo xla('Save'); ?>' onclick='transmitting = false;' />
577 &nbsp;
578 <input type='submit' name='bn_xmit' value='<?php echo xla('Save and Transmit'); ?>' onclick='transmitting = true;' />
579 &nbsp;
580 <input type='button' value='<?php echo xla('Cancel'); ?>' onclick="top.restoreSession();location='<?php echo $GLOBALS['form_exit_url']; ?>'" />
581 </p>
583 </center>
585 <script language='JavaScript'>
586 Calendar.setup({inputField:'form_date_ordered', ifFormat:'%Y-%m-%d',
587 button:'img_date_ordered'});
588 Calendar.setup({inputField:'form_date_collected', ifFormat:'%Y-%m-%d %H:%M',
589 button:'img_date_collected', showsTime:true});
590 </script>
592 </form>
593 </body>
594 </html>