34499e5a5c33a69e43b8ad4df31afa9d32b61c5d
[openemr.git] / interface / main / finder / patient_select.php
blob34499e5a5c33a69e43b8ad4df31afa9d32b61c5d
1 <?php
2 /**
3 * Patient selector screen.
5 * LICENSE: This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
16 * @package OpenEMR
17 * @author Brady Miller <brady@sparmy.com>
18 * @link http://www.open-emr.org
21 //SANITIZE ALL ESCAPES
22 $sanitize_all_escapes=true;
25 //STOP FAKE REGISTER GLOBALS
26 $fake_register_globals=false;
29 require_once("../../globals.php");
30 require_once("$srcdir/patient.inc");
31 require_once("$srcdir/formdata.inc.php");
33 $fstart = isset($_REQUEST['fstart']) ? $_REQUEST['fstart'] : 0;
34 $popup = empty($_REQUEST['popup']) ? 0 : 1;
35 $message = isset($_GET['message']) ? $_GET['message'] : "";
38 <html>
39 <head>
40 <?php html_header_show();?>
42 <link rel=stylesheet href="<?php echo $css_header;?>" type="text/css">
43 <style>
44 form {
45 padding: 0px;
46 margin: 0px;
48 #searchCriteria {
49 text-align: center;
50 width: 100%;
51 font-size: 0.8em;
52 background-color: #ddddff;
53 font-weight: bold;
54 padding: 3px;
56 #searchResultsHeader {
57 width: 100%;
58 background-color: lightgrey;
60 #searchResultsHeader table {
61 width: 96%; /* not 100% because the 'searchResults' table has a scrollbar */
62 border-collapse: collapse;
64 #searchResultsHeader th {
65 font-size: 0.7em;
67 #searchResults {
68 width: 100%;
69 height: 80%;
70 overflow: auto;
73 .srName { width: 12%; }
74 .srPhone { width: 11%; }
75 .srSS { width: 11%; }
76 .srDOB { width: 8%; }
77 .srID { width: 7%; }
78 .srPID { width: 7%; }
79 .srNumEnc { width: 11%; }
80 .srNumDays { width: 11%; }
81 .srDateLast { width: 11%; }
82 .srDateNext { width: 11%; }
83 .srMisc { width: 10%; }
85 #searchResults table {
86 width: 100%;
87 border-collapse: collapse;
88 background-color: white;
90 #searchResults tr {
91 cursor: hand;
92 cursor: pointer;
94 #searchResults td {
95 font-size: 0.7em;
96 border-bottom: 1px solid #eee;
98 .oneResult { }
99 .billing { color: red; font-weight: bold; }
100 .highlight {
101 background-color: #336699;
102 color: white;
104 </style>
106 <script type="text/javascript" src="<?php echo $GLOBALS['webroot'] ?>/library/js/jquery-1.2.2.min.js"></script>
108 <script language="JavaScript">
110 // This is called when forward or backward paging is done.
112 function submitList(offset) {
113 var f = document.forms[0];
114 var i = parseInt(f.fstart.value) + offset;
115 if (i < 0) i = 0;
116 f.fstart.value = i;
117 top.restoreSession();
118 f.submit();
121 </script>
123 </head>
124 <body class="body_top">
126 <form method='post' action='patient_select.php' name='theform' onsubmit='return top.restoreSession()'>
127 <input type='hidden' name='fstart' value='<?php echo htmlspecialchars( $fstart, ENT_QUOTES); ?>' />
129 <?php
130 $MAXSHOW = 100; // maximum number of results to display at once
132 //the maximum number of patient records to display:
133 $sqllimit = $MAXSHOW;
134 $given = "*, DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS";
135 $orderby = "lname ASC, fname ASC";
137 $search_service_code = trim($_POST['search_service_code']);
138 echo "<input type='hidden' name='search_service_code' value='" .
139 htmlspecialchars($search_service_code, ENT_QUOTES) . "' />\n";
141 if ($popup) {
142 echo "<input type='hidden' name='popup' value='1' />\n";
144 // Construct WHERE clause and save search parameters as form fields.
145 $sqlBindArray = array();
146 $where = "1 = 1";
147 $fres = sqlStatement("SELECT * FROM layout_options " .
148 "WHERE form_id = 'DEM' AND uor > 0 AND field_id != '' " .
149 "ORDER BY group_name, seq");
150 while ($frow = sqlFetchArray($fres)) {
151 $field_id = $frow['field_id'];
152 if (strpos($field_id, 'em_') === 0) continue;
153 $data_type = $frow['data_type'];
154 if (!empty($_REQUEST[$field_id])) {
155 $value = trim($_REQUEST[$field_id]);
156 if ($field_id == 'pid') {
157 $where .= " AND $field_id = ?";
158 array_push($sqlBindArray,$value);
160 else if ($field_id == 'pubpid') {
161 $where .= " AND $field_id LIKE ?";
162 array_push($sqlBindArray,$value);
164 else {
165 $where .= " AND $field_id LIKE ?";
166 array_push($sqlBindArray,$value."%");
168 echo "<input type='hidden' name='" . htmlspecialchars( $field_id, ENT_QUOTES) .
169 "' value='" . htmlspecialchars( $value, ENT_QUOTES) . "' />\n";
173 // If a non-empty service code was given, then restrict to patients who
174 // have been provided that service. Since the code is used in a LIKE
175 // clause, % and _ wildcards are supported.
176 if ($search_service_code) {
177 $where .=
178 " AND ( SELECT COUNT(*) FROM billing AS b WHERE " .
179 "b.pid = patient_data.pid AND " .
180 "b.activity = 1 AND " .
181 "b.code_type != 'COPAY' AND " .
182 "b.code LIKE ? " .
183 ") > 0";
184 array_push($sqlBindArray, $search_service_code);
187 $sql = "SELECT $given FROM patient_data " .
188 "WHERE $where ORDER BY $orderby LIMIT $fstart, $sqllimit";
189 $rez = sqlStatement($sql,$sqlBindArray);
190 $result = array();
191 while ($row = sqlFetchArray($rez)) $result[] = $row;
192 _set_patient_inc_count($sqllimit, count($result), $where, $sqlBindArray);
194 else {
195 $patient = $_REQUEST['patient'];
196 $findBy = $_REQUEST['findBy'];
197 $searchFields = $_REQUEST['searchFields'];
199 echo "<input type='hidden' name='patient' value='" . htmlspecialchars( $patient, ENT_QUOTES) . "' />\n";
200 echo "<input type='hidden' name='findBy' value='" . htmlspecialchars( $findBy, ENT_QUOTES) . "' />\n";
202 if ($findBy == "Last")
203 $result = getPatientLnames("$patient", $given, $orderby, $sqllimit, $fstart);
204 else if ($findBy == "ID")
205 $result = getPatientId("$patient", $given, "id ASC, ".$orderby, $sqllimit, $fstart);
206 else if ($findBy == "DOB")
207 $result = getPatientDOB("$patient", $given, "DOB ASC, ".$orderby, $sqllimit, $fstart);
208 else if ($findBy == "SSN")
209 $result = getPatientSSN("$patient", $given, "ss ASC, ".$orderby, $sqllimit, $fstart);
210 elseif ($findBy == "Phone") //(CHEMED) Search by phone number
211 $result = getPatientPhone("$patient", $given, $orderby, $sqllimit, $fstart);
212 else if ($findBy == "Any")
213 $result = getByPatientDemographics("$patient", $given, $orderby, $sqllimit, $fstart);
214 else if ($findBy == "Filter") {
215 $result = getByPatientDemographicsFilter($searchFields, "$patient",
216 $given, $orderby, $sqllimit, $fstart, $search_service_code);
221 </form>
223 <table border='0' cellpadding='5' cellspacing='0' width='100%'>
224 <tr>
225 <td class='text'>
226 <a href="./patient_select_help.php" target=_new onclick='top.restoreSession()'>[<?php echo htmlspecialchars( xl('Help'), ENT_NOQUOTES); ?>]&nbsp</a>
227 </td>
228 <td class='text' align='center'>
229 <?php if ($message) echo "<font color='red'><b>".htmlspecialchars( $message, ENT_NOQUOTES)."</b></font>\n"; ?>
230 </td>
231 <td class='text' align='right'>
232 <?php
233 // Show start and end row number, and number of rows, with paging links.
235 // $count = $fstart + $GLOBALS['PATIENT_INC_COUNT']; // Why did I do that???
236 $count = $GLOBALS['PATIENT_INC_COUNT'];
237 $fend = $fstart + $MAXSHOW;
238 if ($fend > $count) $fend = $count;
240 <?php if ($fstart) { ?>
241 <a href="javascript:submitList(-<?php echo $MAXSHOW ?>)">
242 &lt;&lt;
243 </a>
244 &nbsp;&nbsp;
245 <?php } ?>
246 <?php echo ($fstart + 1) . htmlspecialchars( " - $fend of $count", ENT_NOQUOTES); ?>
247 <?php if ($count > $fend) { ?>
248 &nbsp;&nbsp;
249 <a href="javascript:submitList(<?php echo $MAXSHOW ?>)">
250 &gt;&gt;
251 </a>
252 <?php } ?>
253 </td>
254 </tr>
255 </table>
257 <div id="searchResultsHeader">
258 <table>
259 <tr>
260 <th class="srName"><?php echo htmlspecialchars( xl('Name'), ENT_NOQUOTES);?></th>
261 <th class="srPhone"><?php echo htmlspecialchars( xl('Phone'), ENT_NOQUOTES);?></th>
262 <th class="srSS"><?php echo htmlspecialchars( xl('SS'), ENT_NOQUOTES);?></th>
263 <th class="srDOB"><?php echo htmlspecialchars( xl('DOB'), ENT_NOQUOTES);?></th>
264 <th class="srID"><?php echo htmlspecialchars( xl('ID'), ENT_NOQUOTES);?></th>
266 <?php if (empty($GLOBALS['patient_search_results_style'])) { ?>
267 <th class="srPID"><?php echo htmlspecialchars( xl('PID'), ENT_NOQUOTES);?></th>
268 <th class="srNumEnc"><?php echo htmlspecialchars( xl('[Number Of Encounters]'), ENT_NOQUOTES);?></th>
269 <th class="srNumDays"><?php echo htmlspecialchars( xl('[Days Since Last Encounter]'), ENT_NOQUOTES);?></th>
270 <th class="srDateLast"><?php echo htmlspecialchars( xl('[Date of Last Encounter]'), ENT_NOQUOTES);?></th>
271 <th class="srDateNext">
272 <?php
273 $add_days = 90;
274 if (!$popup && preg_match('/^(\d+)\s*(.*)/',$patient,$matches) > 0) {
275 $add_days = $matches[1];
276 $patient = $matches[2];
279 [<?php echo htmlspecialchars( $add_days, ENT_NOQUOTES);?> <?php echo htmlspecialchars( xl('Days From Last Encounter'), ENT_NOQUOTES); ?>]
280 </th>
282 <?php
284 else {
285 // Alternate patient search results style; this gets address plus other
286 // fields that are mandatory, up to a limit of 5.
287 $extracols = array();
288 $tres = sqlStatement("SELECT field_id, title FROM layout_options " .
289 "WHERE form_id = 'DEM' AND ( uor > 1 AND field_id != '' " .
290 "OR uor > 0 AND field_id = 'street' ) AND " .
291 "field_id NOT LIKE '_name' AND " .
292 "field_id NOT LIKE 'phone%' AND " .
293 "field_id NOT LIKE 'title' AND " .
294 "field_id NOT LIKE 'ss' AND " .
295 "field_id NOT LIKE 'DOB' AND " .
296 "field_id NOT LIKE 'pubpid' " .
297 "ORDER BY group_name, seq LIMIT 5");
298 while ($trow = sqlFetchArray($tres)) {
299 $extracols[$trow['field_id']] = $trow['title'];
300 echo "<th class='srMisc'>" . htmlspecialchars(xl($trow['title']), ENT_NOQUOTES) . "</th>\n";
305 </tr>
306 </table>
307 </div>
309 <div id="searchResults">
311 <table>
312 <tr>
313 <?php
314 if ($result) {
315 foreach ($result as $iter) {
316 echo "<tr class='oneresult' id='".htmlspecialchars( $iter['pid'], ENT_QUOTES)."'>";
317 echo "<td class='srName'>" . htmlspecialchars($iter['lname'] . ", " . $iter['fname']) . "</td>\n";
318 //other phone number display setup for tooltip
319 $phone_biz = '';
320 if ($iter{"phone_biz"} != "") {
321 $phone_biz = " [business phone ".$iter{"phone_biz"}."] ";
323 $phone_contact = '';
324 if ($iter{"phone_contact"} != "") {
325 $phone_contact = " [contact phone ".$iter{"phone_contact"}."] ";
327 $phone_cell = '';
328 if ($iter{"phone_cell"} != "") {
329 $phone_cell = " [cell phone ".$iter{"phone_cell"}."] ";
331 $all_other_phones = $phone_biz.$phone_contact.$phone_cell;
332 if ($all_other_phones == '') {$all_other_phones = xl('No other phone numbers listed');}
333 //end of phone number display setup, now display the phone number(s)
334 echo "<td class='srPhone' title='".htmlspecialchars( $all_other_phones, ENT_QUOTES)."'>" .
335 htmlspecialchars( $iter['phone_home'], ENT_NOQUOTES) . "</td>\n";
337 echo "<td class='srSS'>" . htmlspecialchars( $iter['ss'], ENT_NOQUOTES) . "</td>";
338 if ($iter{"DOB"} != "0000-00-00 00:00:00") {
339 echo "<td class='srDOB'>" . htmlspecialchars( $iter['DOB_TS'], ENT_NOQUOTES) . "</td>";
340 } else {
341 echo "<td class='srDOB'>&nbsp;</td>";
344 echo "<td class='srID'>" . htmlspecialchars( $iter['pubpid'], ENT_NOQUOTES) . "</td>";
346 if (empty($GLOBALS['patient_search_results_style'])) {
348 echo "<td class='srPID'>" . htmlspecialchars( $iter['pid'], ENT_NOQUOTES) . "</td>";
350 //setup for display of encounter date info
351 $encounter_count = 0;
352 $day_diff = '';
353 $last_date_seen = '';
354 $next_appt_date= '';
355 $pid = '';
357 // calculate date differences based on date of last encounter with billing entries
358 $query = "select DATE_FORMAT(max(form_encounter.date),'%m/%d/%y') as mydate," .
359 " (to_days(current_date())-to_days(max(form_encounter.date))) as day_diff," .
360 " DATE_FORMAT(max(form_encounter.date) + interval " .
361 add_escape_custom($add_days) .
362 " day,'%m/%d/%y') as next_appt, dayname(max(form_encounter.date) + interval " .
363 add_escape_custom($add_days) .
364 " day) as next_appt_day from form_encounter " .
365 "join billing on billing.encounter = form_encounter.encounter and " .
366 "billing.pid = form_encounter.pid and billing.activity = 1 and " .
367 "billing.code_type not like 'COPAY' where ".
368 "form_encounter.pid = ?";
369 $statement= sqlStatement($query, array($iter{"pid"}) );
370 if ($results = sqlFetchArray($statement)) {
371 $last_date_seen = $results['mydate'];
372 $day_diff = $results['day_diff'];
373 $next_appt_date= $results['next_appt_day'].', '.$results['next_appt'];
375 // calculate date differences based on date of last encounter regardless of billing
376 $query = "select DATE_FORMAT(max(form_encounter.date),'%m/%d/%y') as mydate," .
377 " (to_days(current_date())-to_days(max(form_encounter.date))) as day_diff," .
378 " DATE_FORMAT(max(form_encounter.date) + interval " .
379 add_escape_custom($add_days) .
380 " day,'%m/%d/%y') as next_appt, dayname(max(form_encounter.date) + interval " .
381 add_escape_custom($add_days) .
382 " day) as next_appt_day from form_encounter " .
383 " where form_encounter.pid = ?";
384 $statement= sqlStatement($query, array($iter{"pid"}) );
385 if ($results = sqlFetchArray($statement)) {
386 $last_date_seen = $results['mydate'];
387 $day_diff = $results['day_diff'];
388 $next_appt_date= $results['next_appt_day'].', '.$results['next_appt'];
391 //calculate count of encounters by distinct billing dates with cpt4
392 //entries
393 $query = "select count(distinct date) as encounter_count " .
394 " from billing ".
395 " where code_type not like 'COPAY' and activity = 1 " .
396 " and pid = ?";
397 $statement= sqlStatement($query, array($iter{"pid"}) );
398 if ($results = sqlFetchArray($statement)) {
399 $encounter_count_billed = $results['encounter_count'];
401 // calculate count of encounters, regardless of billing
402 $query = "select count(date) as encounter_count ".
403 " from form_encounter where ".
404 " pid = ?";
405 $statement= sqlStatement($query, array($iter{"pid"}) );
406 if ($results = sqlFetchArray($statement)) {
407 $encounter_count = $results['encounter_count'];
409 echo "<td class='srNumEnc'>" . htmlspecialchars( $encounter_count, ENT_NOQUOTES) . "</td>\n";
410 echo "<td class='srNumDay'>" . htmlspecialchars( $day_diff, ENT_NOQUOTES) . "</td>\n";
411 echo "<td class='srDateLast'>" . htmlspecialchars( $last_date_seen, ENT_NOQUOTES) . "</td>\n";
412 echo "<td class='srDateNext'>" . htmlspecialchars( $next_appt_date, ENT_NOQUOTES) . "</td>\n";
415 else { // alternate search results style
416 foreach ($extracols as $field_id => $title) {
417 echo "<td class='srMisc'>" . htmlspecialchars( $iter[$field_id], ENT_NOQUOTES) . "</td>\n";
423 </table>
424 </div> <!-- end searchResults DIV -->
426 <script language="javascript">
428 // jQuery stuff to make the page a little easier to use
430 $(document).ready(function(){
431 // $("#searchparm").focus();
432 $(".oneresult").mouseover(function() { $(this).addClass("highlight"); });
433 $(".oneresult").mouseout(function() { $(this).removeClass("highlight"); });
434 $(".oneresult").click(function() { SelectPatient(this); });
435 // $(".event").dblclick(function() { EditEvent(this); });
438 var SelectPatient = function (eObj) {
439 <?php
440 // For the old layout we load a frameset that also sets up the new pid.
441 // The new layout loads just the demographics frame here, which in turn
442 // will set the pid and load all the other frames.
443 if ($GLOBALS['concurrent_layout']) {
444 $newPage = "../../patient_file/summary/demographics.php?set_pid=";
445 $target = "document";
447 else {
448 $newPage = "../../patient_file/patient_file.php?set_pid=";
449 $target = "top";
452 objID = eObj.id;
453 var parts = objID.split("~");
454 <?php if ($popup) echo "opener."; echo $target; ?>.location.href = '<?php echo $newPage; ?>' + parts[0];
455 <?php if ($popup) echo "window.close();\n"; ?>
456 return true;
459 </script>
461 </body>
462 </html>