7 * @link http://www.open-emr.org
8 * @author Brady Miller <brady.g.miller@gmail.com>
9 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 require_once("../../../interface/globals.php");
14 require_once("./Utils.php");
16 use OpenEMR\Common\Acl\AclMain
;
17 use OpenEMR\Common\Csrf\CsrfUtils
;
18 use OpenEMR\Common\Twig\TwigContainer
;
19 use OpenEMR\Core\Header
;
22 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
23 CsrfUtils
::csrfNotVerified();
25 foreach ($_POST as $key => $value) {
26 $parameters[$key] = $value;
30 if (!AclMain
::aclCheckCore('admin', 'super')) {
31 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Duplication Check")]);
35 /* Use this code to identify duplicate patients in OpenEMR
39 // establish some defaults
40 if (! isset($parameters['sortby'])) {
41 $parameters['sortby'] = "name";
44 if (! isset($parameters['limit'])) {
45 $parameters['limit'] = 100;
49 ! isset($parameters['match_name']) &&
50 ! isset($parameters['match_dob']) &&
51 ! isset($parameters['match_sex']) &&
52 ! isset($parameters['match_ssn'])
54 $parameters['match_name'] = 'on';
55 $parameters['match_dob'] = 'on';
60 <?php Header
::setupHeader(['no_bootstrap', 'no_fontawesome', 'no_main-theme', 'no_textformat', 'no_dialog']); ?
>
63 font
-family
: arial
, helvetica
, times
new roman
;
65 background
-color
: #eee;
68 border
: 1px solid
#eee;
69 background
-color
: white
;
74 border
-collapse
: collapse
;
76 .match_block table tr
{
79 .match_block table td
{
84 background
-color
: #99a;
88 background
-color
: #ffa;
97 <form name
="search_form" id
="search_form" method
="post" action
="index.php">
98 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
99 <input type
="hidden" name
="go" value
="Go">
101 <input type
="checkbox" name
="match_name" id
="match_name" <?php
echo ($parameters['match_name']) ?
"CHECKED" : ""; ?
>>
102 <label
for="match_name">Name
</label
>
103 <input type
="checkbox" name
="match_dob" id
="match_dob" <?php
echo ($parameters['match_dob']) ?
"CHECKED" : ""; ?
>>
104 <label
for="match_dob">DOB
</label
>
105 <input type
="checkbox" name
="match_sex" id
="match_sex" <?php
echo ($parameters['match_sex']) ?
"CHECKED" : ""; ?
>>
106 <label
for="match_sex">Gender
</label
>
107 <input type
="checkbox" name
="match_ssn" id
="match_ssn" <?php
echo ($parameters['match_ssn']) ?
"CHECKED" : ""; ?
>>
108 <label
for="match_ssn">SSN
</label
>
111 <input type
='radio' name
='sortby' value
='name' id
="name" <?php
echo ($parameters['sortby'] == 'name') ?
"CHECKED" : ""; ?
>>
112 <label
for="name">Name
</label
>
113 <input type
='radio' name
='sortby' value
='dob' id
="dob" <?php
echo ($parameters['sortby'] == 'dob') ?
"CHECKED" : ""; ?
>>
114 <label
for="dob">DOB
</label
>
115 <input type
='radio' name
='sortby' value
='sex' id
="sex" <?php
echo ($parameters['sortby'] == 'sex') ?
"CHECKED" : ""; ?
>>
116 <label
for="sex">Gender
</label
>
117 <input type
='radio' name
='sortby' value
='ssn' id
="ssn" <?php
echo ($parameters['sortby'] == 'ssn') ?
"CHECKED" : ""; ?
>>
118 <label
for="ssn">SSN
</label
>
120 Limit search to first
<input type
='textbox' size
='5' name
='limit' id
="limit" value
='<?php echo attr($parameters['limit
']); ?>'> records
121 <input type
="button" name
="do_search" id
="do_search" value
="Go">
124 <div id
="thebiglist" style
="height: 300px; overflow: auto; border: 1px solid blue;">
125 <form name
="resolve" id
="resolve" method
="POST" action
="dupcheck.php">
128 if ($parameters['go'] == "Go") {
129 // go and do the search
131 // counter that gathers duplicates into groups
134 // for EACH patient in OpenEMR find potential matches
135 $sqlstmt = "select id, pid, fname, lname, dob, sex, ss from patient_data";
136 switch ($parameters['sortby']) {
138 $orderby = " ORDER BY dob";
141 $orderby = " ORDER BY sex";
144 $orderby = " ORDER BY ss";
148 $orderby = " ORDER BY lname, fname";
152 $sqlstmt .= $orderby;
153 if ($parameters['limit']) {
154 $sqlstmt .= " LIMIT 0," . escape_limit($parameters['limit']);
157 $qResults = sqlStatement($sqlstmt);
158 while ($row = sqlFetchArray($qResults)) {
159 if ($dupelist[$row['id']] == 1) {
163 $sqlBindArray = array();
164 $sqlstmt = "select id, pid, fname, lname, dob, sex, ss " .
165 " from patient_data where ";
167 if ($parameters['match_name']) {
168 $sqlstmt .= $sqland . " fname=?";
170 $sqlstmt .= $sqland . " lname=?";
171 array_push($sqlBindArray, $row['fname'], $row['lname']);
174 if ($parameters['match_sex']) {
175 $sqlstmt .= $sqland . " sex=?";
177 array_push($sqlBindArray, $row['sex']);
180 if ($parameters['match_ssn']) {
181 $sqlstmt .= $sqland . " ss=?";
183 array_push($sqlBindArray, $row['ss']);
186 if ($parameters['match_dob']) {
187 $sqlstmt .= $sqland . " dob=?";
189 array_push($sqlBindArray, $row['dob']);
192 $mResults = sqlStatement($sqlstmt, $sqlBindArray);
198 if (sqlNumRows($mResults) <= 1) {
203 echo "<div class='match_block' style='padding: 5px 0px 5px 0px;' id='dupediv" . attr($dupecount) . "'>";
206 echo "<tr class='onerow' id='" . attr($row['id']) . "' oemrid='" . attr($row['id']) . "' dupecount='" . attr($dupecount) . "' title='Merge duplicates into this record'>";
207 echo "<td>" . text($row['lname']) . ", " . text($row['fname']) . "</td>";
208 echo "<td>" . text($row['dob']) . "</td>";
209 echo "<td>" . text($row['sex']) . "</td>";
210 echo "<td>" . text($row['ss']) . "</td>";
211 echo "<td><input type='button' value=' ? ' class='moreinfo' oemrid='" . attr($row['pid']) . "' title='More info'></td>";
214 while ($mrow = sqlFetchArray($mResults)) {
215 if ($row['id'] == $mrow['id']) {
219 echo "<tr class='onerow' id='" . attr($mrow['id']) . "' oemrid='" . attr($mrow['id']) . "' dupecount='" . attr($dupecount) . "' title='Merge duplicates into this record'>";
220 echo "<td>" . text($mrow['lname']) . ", " . text($mrow['fname']) . "</td>";
221 echo "<td>" . text($mrow['dob']) . "</td>";
222 echo "<td>" . text($mrow['sex']) . "</td>";
223 echo "<td>" . text($mrow['ss']) . "</td>";
224 echo "<td><input type='button' value=' ? ' class='moreinfo' oemrid='" . attr($mrow['pid']) . "' title='More info'></td>";
226 // to keep the output clean let's not repeat IDs already tagged as dupes
227 $dupelist[$row['id']] = 1;
228 $dupelist[$mrow['id']] = 1;
239 </div
> <!-- end the big
list -->
240 <?php
if ($dupecount > 0) : ?
>
241 <div id
="dupecounter" style
='display:inline;'><?php
echo text($dupecount); ?
></div
>
242  
;duplicates found
252 // capture RETURN keypress
253 $
("#limit").on("keypress", function(evt
) { if (evt
.keyCode
== 13) $
("#do_search").click(); });
255 // perform the database search for duplicates
256 $
("#do_search").on("click", function() {
257 $
("#thebiglist").html("<p style='margin:10px;'><img src='<?php echo $GLOBALS['webroot']; ?>/interface/pic/ajax-loader.gif'> Searching ...</p>");
258 $
("#search_form").trigger("submit");
262 // pop up an OpenEMR window directly to the patient info
263 var moreinfoWin
= null;
264 $
(".moreinfo").on("click", function(evt
) {
265 if (moreinfoWin
) { moreinfoWin
.close(); }
266 moreinfoWin
= window
.open("<?php echo $GLOBALS['webroot']; ?>/interface/patient_file/patient_file.php?set_pid=" +
encodeURIComponent($
(this
).attr("oemrid")), "moreinfo");
267 evt
.stopPropagation();
270 // highlight the block of matching records
271 $
(".match_block").on("mouseover", function() { $
(this
).toggleClass("highlight_block"); });
272 $
(".match_block").on("mouseout", function() { $
(this
).toggleClass("highlight_block"); });
273 $
(".onerow").on("mouseover", function() { $
(this
).toggleClass("highlight"); });
274 $
(".onerow").on("mouseout", function() { $
(this
).toggleClass("highlight"); });
276 // begin the merge of a block into a single record
277 $
(".onerow").on("click", function() {
278 var dupecount
= $
(this
).attr("dupecount");
279 var masterid
= $
(this
).attr("oemrid");
280 var newurl
= "mergerecords.php?dupecount=" +
encodeURIComponent(dupecount
) +
"&masterid=" +
encodeURIComponent(masterid
) +
'&csrf_token_form=' +
<?php
echo js_url(CsrfUtils
::collectCsrfToken()); ?
>;
281 $
("[dupecount="+dupecount+
"]").each(function (i
) {
282 if (this
.id
!= masterid
) { newurl +
= "&otherid[]=" +
encodeURIComponent(this
.id
); }
284 // open a new window and show the merge results
285 moreinfoWin
= window
.open(newurl
, "mergewin");
289 function removedupe(dupeid
) {
290 // remove the merged records from the list of duplicates
291 $
("#dupediv"+dupeid
).remove();
292 // reduce the duplicate counter
293 var dcounter
= parseInt($
("#dupecounter").html());
294 $
("#dupecounter").html(dcounter
-1);