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.php");
15 require_once("$srcdir/options.inc.php");
17 use OpenEMR\Common\Acl\AclMain
;
18 use OpenEMR\Common\Csrf\CsrfUtils
;
19 use OpenEMR\Common\Twig\TwigContainer
;
20 use OpenEMR\Core\Header
;
21 use OpenEMR\Services\FacilityService
;
25 function displayRow($row, $pid = '')
37 if (isset($row['myscore'])) {
38 $myscore = $row['myscore'];
39 $options = "<option value=''></option>" .
40 "<option value='MK'>" . xlt('Merge and Keep') . "</option>" .
41 "<option value='MD'>" . xlt('Merge and Discard') . "</option>";
43 $myscore = $row['dupscore'];
44 $options = "<option value=''></option>" .
45 "<option value='U'>" . xlt('Mark as Unique') . "</option>" .
46 "<option value='R'>" . xlt('Recompute Score') . "</option>";
48 echo " <tr bgcolor='#dddddd'><td class='detail' colspan='12'> </td></tr>\n";
53 $ptname = $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
55 if (trim($row['phone_home'])) {
56 $phones[] = trim($row['phone_home']);
58 if (trim($row['phone_biz' ])) {
59 $phones[] = trim($row['phone_biz' ]);
61 if (trim($row['phone_cell'])) {
62 $phones[] = trim($row['phone_cell']);
64 $phones = implode(', ', $phones);
67 if ($row['home_facility']) {
68 $facrow = getFacility($row['home_facility']);
69 if (!empty($facrow['name'])) {
70 $facname = $facrow['name'];
74 <tr bgcolor
='<?php echo $bgcolor; ?>'>
75 <td
class="detail" bgcolor
="#dddddd">
76 <select onchange
='selchange(this, <?php echo attr_js($pid); ?>, <?php echo attr_js($row['pid
']); ?>)' style
='width:100%'>
77 <?php
echo $options; // this is html and already escaped as required ?>
80 <td
class="detail" align
="right">
81 <?php
echo text($myscore); ?
>
83 <td
class="detail" align
="right" onclick
="openNewTopWindow(<?php echo attr_js($row['pid']); ?>)"
84 title
="<?php echo xla('Click to open in a new window or tab'); ?>" style
="color:blue;cursor:pointer">
85 <?php
echo text($row['pid']); ?
>
88 <?php
echo text($row['pubpid']); ?
>
91 <?php
echo text($ptname); ?
>
94 <?php
echo text(oeFormatShortDate($row['DOB'])); ?
>
97 <?php
echo text($row['ss']); ?
>
100 <?php
echo text($row['email']); ?
>
103 <?php
echo text($phones); ?
>
106 <?php
echo text(oeFormatShortDate($row['regdate'])); ?
>
109 <?php
echo text($facname); ?
>
112 <?php
echo text($row['street']); ?
>
118 if (!empty($_POST)) {
119 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
120 CsrfUtils
::csrfNotVerified();
124 if (!AclMain
::aclCheckCore('admin', 'super')) {
125 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Duplicate Patient Management")]);
129 $scorecalc = getDupScoreSQL();
133 <title
><?php
echo xlt('Duplicate Patient Management') ?
></title
>
135 <?php Header
::setupHeader(['report-helper']); ?
>
137 <style type
="text/css">
139 .dehead
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
140 .detail
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
141 .delink
{ color
:#0000cc; font-family:sans-serif; font-size:10pt; font-weight:normal; cursor:pointer }
143 table
.mymaintable
, table
.mymaintable td
{
144 border
: 1px solid
#aaaaaa;
145 border
-collapse
: collapse
;
147 table
.mymaintable td
{
148 padding
: 1pt
4pt
1pt
4pt
;
156 // Enable fixed headers when scrolling the report.
157 if (window
.oeFixedHeaderSetup
) {
158 oeFixedHeaderSetup(document
.getElementById('mymaintable'));
162 function openNewTopWindow(pid
) {
163 document
.fnew
.patientID
.value
= pid
;
164 top
.restoreSession();
165 document
.fnew
.submit();
168 function selchange(sel
, toppid
, rowpid
) {
169 var f
= document
.forms
[0];
170 if (sel
.value
== '') return;
171 top
.restoreSession();
172 if (sel
.value
== 'MK') {
173 window
.location
= 'merge_patients.php?pid1=' +
encodeURIComponent(rowpid
) +
'&pid2=' +
encodeURIComponent(toppid
);
175 else if (sel
.value
== 'MD') {
176 window
.location
= 'merge_patients.php?pid1=' +
encodeURIComponent(toppid
) +
'&pid2=' +
encodeURIComponent(rowpid
);
179 // Currently 'U' and 'R' actions are supported and rowpid is meaningless.
180 f
.form_action
.value
= sel
.value
;
181 f
.form_toppid
.value
= toppid
;
182 f
.form_rowpid
.value
= rowpid
;
191 <body style
='margin: 2em; background-color: #dddddd' >
194 <h2
><?php
echo xlt('Duplicate Patient Management')?
></h2
>
196 <form method
='post' action
='manage_dup_patients.php'>
197 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
199 <table border
='0' cellpadding
='3'>
202 <input type
='submit' name
='form_refresh' value
="<?php echo xla('Refresh') ?>">
204 <input type
='button' value
='<?php echo xla('Print'); ?>' onclick
='window.print()' />
213 <table id
='mymaintable' class='mymaintable'>
215 <tr bgcolor
="#dddddd">
217 <?php
echo xlt('Actions'); ?
>
219 <td
class="dehead" align
="right">
220 <?php
echo xlt('Score'); ?
>
222 <td
class="dehead" align
="right">
223 <?php
echo xlt('Pid'); ?
>
226 <?php
echo xlt('ID'); ?
>
229 <?php
echo xlt('Name'); ?
>
232 <?php
echo xlt('DOB'); ?
>
235 <?php
echo xlt('SSN'); ?
>
238 <?php
echo xlt('Email'); ?
>
241 <?php
echo xlt('Telephone'); ?
>
244 <?php
echo xlt('Registered'); ?
>
247 <?php
echo xlt('Home Facility'); ?
>
250 <?php
echo xlt('Address'); ?
>
257 $form_action = $_POST['form_action'] ??
'';
259 if ($form_action == 'U') {
261 "UPDATE patient_data SET dupscore = -1 WHERE pid = ?",
262 array($_POST['form_toppid'])
264 } else if ($form_action == 'R') {
265 updateDupScore($_POST['form_toppid']);
268 $query = "SELECT * FROM patient_data WHERE dupscore > 7 " .
269 "ORDER BY dupscore DESC, pid DESC LIMIT 100";
270 $res1 = sqlStatement($query);
271 while ($row1 = sqlFetchArray($res1)) {
273 $query = "SELECT p2.*, ($scorecalc) AS myscore " .
274 "FROM patient_data AS p1, patient_data AS p2 WHERE " .
275 "p1.pid = ? AND p2.pid < p1.pid AND ($scorecalc) > 7 " .
276 "ORDER BY myscore DESC, p2.pid DESC";
277 $res2 = sqlStatement($query, array($row1['pid']));
278 while ($row2 = sqlFetchArray($res2)) {
279 displayRow($row2, $row1['pid']);
285 <input type
='hidden' name
='form_action' value
='' />
286 <input type
='hidden' name
='form_toppid' value
='0' />
287 <input type
='hidden' name
='form_rowpid' value
='0' />
291 <!-- form used to open a
new top level window when a patient row is clicked
-->
292 <form name
='fnew' method
='post' target
='_blank'
293 action
='../main/main_screen.php?auth=login&site=<?php echo attr_url($_SESSION['site_id
']); ?>'>
294 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
295 <input type
='hidden' name
='patientID' value
='0' />