fix: send each checked encounter to collections in form export (#7769)
[openemr.git] / contrib / util / dupecheck / index.php
blobbf0bba5aae1b8d3e9d19b81a95b364cd26f87ca2
1 <?php
3 /**
4 * dupecheck index.php
6 * @package OpenEMR
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;
21 if (!empty($_POST)) {
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")]);
32 exit;
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;
48 if (
49 ! isset($parameters['match_name']) &&
50 ! isset($parameters['match_dob']) &&
51 ! isset($parameters['match_sex']) &&
52 ! isset($parameters['match_ssn'])
53 ) {
54 $parameters['match_name'] = 'on';
55 $parameters['match_dob'] = 'on';
58 <html>
59 <head>
60 <?php Header::setupHeader(['no_bootstrap', 'no_fontawesome', 'no_main-theme', 'no_textformat', 'no_dialog']); ?>
61 <style>
62 body {
63 font-family: arial, helvetica, times new roman;
64 font-size: 1em;
65 background-color: #eee;
67 .match_block {
68 border: 1px solid #eee;
69 background-color: white;
70 padding: 5px;
73 .match_block table {
74 border-collapse: collapse;
76 .match_block table tr {
77 cursor: pointer;
79 .match_block table td {
80 padding: 5px;
83 .highlight {
84 background-color: #99a;
85 color: white;
87 .highlight_block {
88 background-color: #ffa;
90 .bold {
91 font-weight: bold;
94 </style>
95 </head>
96 <body>
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">
100 Matching criteria:
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>
109 <br />
110 Order results by:
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>
119 <br />
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">
122 </form>
124 <div id="thebiglist" style="height: 300px; overflow: auto; border: 1px solid blue;">
125 <form name="resolve" id="resolve" method="POST" action="dupcheck.php">
127 <?php
128 if ($parameters['go'] == "Go") {
129 // go and do the search
131 // counter that gathers duplicates into groups
132 $dupecount = 0;
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']) {
137 case 'dob':
138 $orderby = " ORDER BY dob";
139 break;
140 case 'sex':
141 $orderby = " ORDER BY sex";
142 break;
143 case 'ssn':
144 $orderby = " ORDER BY ss";
145 break;
146 case 'name':
147 default:
148 $orderby = " ORDER BY lname, fname";
149 break;
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) {
160 continue;
163 $sqlBindArray = array();
164 $sqlstmt = "select id, pid, fname, lname, dob, sex, ss " .
165 " from patient_data where ";
166 $sqland = "";
167 if ($parameters['match_name']) {
168 $sqlstmt .= $sqland . " fname=?";
169 $sqland = " AND ";
170 $sqlstmt .= $sqland . " lname=?";
171 array_push($sqlBindArray, $row['fname'], $row['lname']);
174 if ($parameters['match_sex']) {
175 $sqlstmt .= $sqland . " sex=?";
176 $sqland = " AND ";
177 array_push($sqlBindArray, $row['sex']);
180 if ($parameters['match_ssn']) {
181 $sqlstmt .= $sqland . " ss=?";
182 $sqland = " AND ";
183 array_push($sqlBindArray, $row['ss']);
186 if ($parameters['match_dob']) {
187 $sqlstmt .= $sqland . " dob=?";
188 $sqland = " AND ";
189 array_push($sqlBindArray, $row['dob']);
192 $mResults = sqlStatement($sqlstmt, $sqlBindArray);
194 if (! $mResults) {
195 continue;
198 if (sqlNumRows($mResults) <= 1) {
199 continue;
203 echo "<div class='match_block' style='padding: 5px 0px 5px 0px;' id='dupediv" . attr($dupecount) . "'>";
204 echo "<table>";
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>";
212 echo "</tr>";
214 while ($mrow = sqlFetchArray($mResults)) {
215 if ($row['id'] == $mrow['id']) {
216 continue;
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>";
225 echo "</tr>";
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;
231 $dupecount++;
233 echo "</table>";
234 echo "</div>\n";
239 </div> <!-- end the big list -->
240 <?php if ($dupecount > 0) : ?>
241 <div id="dupecounter" style='display:inline;'><?php echo text($dupecount); ?></div>
242 &nbsp;duplicates found
243 <?php endif; ?>
244 </form>
246 </body>
248 <script>
250 $(function () {
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");
259 return true;
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);
297 </script>
299 </html>