4 * This tool helps with identifying and merging duplicate patients.
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
;
24 function displayRow($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>";
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>";
47 echo " <tr bgcolor='#dddddd'><td class='detail' colspan='12'> </td></tr>\n";
52 $ptname = $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
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);
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 ?>
79 <td
class="detail" align
="right">
80 <?php
echo text($myscore); ?
>
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']); ?
>
87 <?php
echo text($row['pubpid']); ?
>
90 <?php
echo text($ptname); ?
>
93 <?php
echo text(oeFormatShortDate($row['DOB'])); ?
>
96 <?php
echo text($row['ss']); ?
>
99 <?php
echo text($row['email']); ?
>
102 <?php
echo text($phones); ?
>
105 <?php
echo text(oeFormatShortDate($row['regdate'])); ?
>
108 <?php
echo text($facname); ?
>
111 <?php
echo text($row['street']); ?
>
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();
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
;
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
);
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
;
189 <body style
='margin: 2em; background-color: #dddddd' >
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'>
200 <input type
='submit' name
='form_refresh' value
="<?php echo xla('Refresh') ?>">
202 <input type
='button' value
='<?php echo xla('Print'); ?>' onclick
='window.print()' />
211 <table id
='mymaintable' class='mymaintable'>
213 <tr bgcolor
="#dddddd">
215 <?php
echo xlt('Actions'); ?
>
217 <td
class="dehead" align
="right">
218 <?php
echo xlt('Score'); ?
>
220 <td
class="dehead" align
="right">
221 <?php
echo xlt('Pid'); ?
>
224 <?php
echo xlt('ID'); ?
>
227 <?php
echo xlt('Name'); ?
>
230 <?php
echo xlt('DOB'); ?
>
233 <?php
echo xlt('SSN'); ?
>
236 <?php
echo xlt('Email'); ?
>
239 <?php
echo xlt('Telephone'); ?
>
242 <?php
echo xlt('Registered'); ?
>
245 <?php
echo xlt('Home Facility'); ?
>
248 <?php
echo xlt('Address'); ?
>
255 $form_action = $_POST['form_action'] ??
'';
257 if ($form_action == 'U') {
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)) {
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']);
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' />
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' />