Implemented duplicate patients management. (#4502)
[openemr.git] / interface / patient_file / manage_dup_patients.php
blob5ac65e2813d504c3d79eda7a1ca8ef7e44c242a7
1 <?php
3 /*
4 * This tool helps with identifying and merging duplicate patients.
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @copyright Copyright (c) 2017-2021 Rod Roark <rod@sunsetsystems.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 require_once("../globals.php");
14 require_once("$srcdir/patient.inc");
15 require_once("$srcdir/options.inc.php");
17 use OpenEMR\Common\Acl\AclMain;
18 use OpenEMR\Common\Csrf\CsrfUtils;
19 use OpenEMR\Core\Header;
20 use OpenEMR\Services\FacilityService;
22 $firsttime = true;
24 function displayRow($row, $pid = '')
26 global $firsttime;
28 $bgcolor = '#ffdddd';
29 $myscore = '';
30 $options = '';
32 if (empty($pid)) {
33 $pid = $row['pid'];
36 if (isset($row['myscore'])) {
37 $myscore = $row['myscore'];
38 $options = "<option value=''></option>" .
39 "<option value='MK'>" . xlt('Merge and Keep') . "</option>" .
40 "<option value='MD'>" . xlt('Merge and Discard') . "</option>";
41 } else {
42 $myscore = $row['dupscore'];
43 $options = "<option value=''></option>" .
44 "<option value='U'>" . xlt('Mark as Unique') . "</option>" .
45 "<option value='R'>" . xlt('Recompute Score') . "</option>";
46 if (!$firsttime) {
47 echo " <tr bgcolor='#dddddd'><td class='detail' colspan='12'>&nbsp;</td></tr>\n";
51 $firsttime = false;
52 $ptname = $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
53 $phones = array();
54 if (trim($row['phone_home'])) {
55 $phones[] = trim($row['phone_home']);
57 if (trim($row['phone_biz' ])) {
58 $phones[] = trim($row['phone_biz' ]);
60 if (trim($row['phone_cell'])) {
61 $phones[] = trim($row['phone_cell']);
63 $phones = implode(', ', $phones);
65 $facname = '';
66 if ($row['home_facility']) {
67 $facrow = getFacility($row['home_facility']);
68 if (!empty($facrow['name'])) {
69 $facname = $facrow['name'];
73 <tr bgcolor='<?php echo $bgcolor; ?>'>
74 <td class="detail" bgcolor="#dddddd">
75 <select onchange='selchange(this, <?php echo attr_js($pid); ?>, <?php echo attr_js($row['pid']); ?>)' style='width:100%'>
76 <?php echo $options; // this is html and already escaped as required ?>
77 </select>
78 </td>
79 <td class="detail" align="right">
80 <?php echo text($myscore); ?>
81 </td>
82 <td class="detail" align="right" onclick="openNewTopWindow(<?php echo attr_js($row['pid']); ?>)"
83 title="<?php echo xla('Click to open in a new window or tab'); ?>" style="color:blue;cursor:pointer">
84 <?php echo text($row['pid']); ?>
85 </td>
86 <td class="detail">
87 <?php echo text($row['pubpid']); ?>
88 </td>
89 <td class="detail">
90 <?php echo text($ptname); ?>
91 </td>
92 <td class="detail">
93 <?php echo text(oeFormatShortDate($row['DOB'])); ?>
94 </td>
95 <td class="detail">
96 <?php echo text($row['ss']); ?>
97 </td>
98 <td class="detail">
99 <?php echo text($row['email']); ?>
100 </td>
101 <td class="detail">
102 <?php echo text($phones); ?>
103 </td>
104 <td class="detail">
105 <?php echo text(oeFormatShortDate($row['regdate'])); ?>
106 </td>
107 <td class="detail">
108 <?php echo text($facname); ?>
109 </td>
110 <td class="detail">
111 <?php echo text($row['street']); ?>
112 </td>
113 </tr>
114 <?php
117 if (!empty($_POST)) {
118 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
119 CsrfUtils::csrfNotVerified();
123 if (!AclMain::aclCheckCore('admin', 'super')) {
124 die(xlt("Unauthorized access."));
127 $scorecalc = getDupScoreSQL();
129 <html>
130 <head>
131 <title><?php echo xlt('Duplicate Patient Management') ?></title>
133 <?php Header::setupHeader(['report-helper']); ?>
135 <style type="text/css">
137 .dehead { color:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
138 .detail { color:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
139 .delink { color:#0000cc; font-family:sans-serif; font-size:10pt; font-weight:normal; cursor:pointer }
141 table.mymaintable, table.mymaintable td {
142 border: 1px solid #aaaaaa;
143 border-collapse: collapse;
145 table.mymaintable td {
146 padding: 1pt 4pt 1pt 4pt;
149 </style>
151 <script>
153 $(function () {
154 // Enable fixed headers when scrolling the report.
155 if (window.oeFixedHeaderSetup) {
156 oeFixedHeaderSetup(document.getElementById('mymaintable'));
160 function openNewTopWindow(pid) {
161 document.fnew.patientID.value = pid;
162 top.restoreSession();
163 document.fnew.submit();
166 function selchange(sel, toppid, rowpid) {
167 var f = document.forms[0];
168 if (sel.value == '') return;
169 top.restoreSession();
170 if (sel.value == 'MK') {
171 window.location = 'merge_patients.php?pid1=' + encodeURIComponent(rowpid) + '&pid2=' + encodeURIComponent(toppid);
173 else if (sel.value == 'MD') {
174 window.location = 'merge_patients.php?pid1=' + encodeURIComponent(toppid) + '&pid2=' + encodeURIComponent(rowpid);
176 else {
177 // Currently 'U' and 'R' actions are supported and rowpid is meaningless.
178 f.form_action.value = sel.value;
179 f.form_toppid.value = toppid;
180 f.form_rowpid.value = rowpid;
181 f.submit();
185 </script>
187 </head>
189 <body style='margin: 2em; background-color: #dddddd' >
190 <center>
192 <h2><?php echo xlt('Duplicate Patient Management')?></h2>
194 <form method='post' action='manage_dup_patients.php'>
195 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
197 <table border='0' cellpadding='3'>
198 <tr>
199 <td align='center'>
200 <input type='submit' name='form_refresh' value="<?php echo xla('Refresh') ?>">
201 &nbsp;
202 <input type='button' value='<?php echo xla('Print'); ?>' onclick='window.print()' />
203 </td>
204 </tr>
205 <tr>
206 <td height="1">
207 </td>
208 </tr>
209 </table>
211 <table id='mymaintable' class='mymaintable'>
212 <thead>
213 <tr bgcolor="#dddddd">
214 <td class="dehead">
215 <?php echo xlt('Actions'); ?>
216 </td>
217 <td class="dehead" align="right">
218 <?php echo xlt('Score'); ?>
219 </td>
220 <td class="dehead" align="right">
221 <?php echo xlt('Pid'); ?>
222 </td>
223 <td class="dehead">
224 <?php echo xlt('ID'); ?>
225 </td>
226 <td class="dehead">
227 <?php echo xlt('Name'); ?>
228 </td>
229 <td class="dehead">
230 <?php echo xlt('DOB'); ?>
231 </td>
232 <td class="dehead">
233 <?php echo xlt('SSN'); ?>
234 </td>
235 <td class="dehead">
236 <?php echo xlt('Email'); ?>
237 </td>
238 <td class="dehead">
239 <?php echo xlt('Telephone'); ?>
240 </td>
241 <td class="dehead">
242 <?php echo xlt('Registered'); ?>
243 </td>
244 <td class="dehead">
245 <?php echo xlt('Home Facility'); ?>
246 </td>
247 <td class="dehead">
248 <?php echo xlt('Address'); ?>
249 </td>
250 </tr>
251 </thead>
252 <tbody>
253 <?php
255 $form_action = $_POST['form_action'] ?? '';
257 if ($form_action == 'U') {
258 sqlStatement(
259 "UPDATE patient_data SET dupscore = -1 WHERE pid = ?",
260 array($_POST['form_toppid'])
262 } else if ($form_action == 'R') {
263 updateDupScore($_POST['form_toppid']);
266 $query = "SELECT * FROM patient_data WHERE dupscore > 7 " .
267 "ORDER BY dupscore DESC, pid DESC LIMIT 100";
268 $res1 = sqlStatement($query);
269 while ($row1 = sqlFetchArray($res1)) {
270 displayRow($row1);
271 $query = "SELECT p2.*, ($scorecalc) AS myscore " .
272 "FROM patient_data AS p1, patient_data AS p2 WHERE " .
273 "p1.pid = ? AND p2.pid < p1.pid AND ($scorecalc) > 7 " .
274 "ORDER BY myscore DESC, p2.pid DESC";
275 $res2 = sqlStatement($query, array($row1['pid']));
276 while ($row2 = sqlFetchArray($res2)) {
277 displayRow($row2, $row1['pid']);
281 </tbody>
282 </table>
283 <input type='hidden' name='form_action' value='' />
284 <input type='hidden' name='form_toppid' value='0' />
285 <input type='hidden' name='form_rowpid' value='0' />
286 </form>
287 </center>
289 <!-- form used to open a new top level window when a patient row is clicked -->
290 <form name='fnew' method='post' target='_blank'
291 action='../main/main_screen.php?auth=login&site=<?php echo attr_url($_SESSION['site_id']); ?>'>
292 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
293 <input type='hidden' name='patientID' value='0' />
294 </form>
296 </body>
297 </html>