Security fixes 22
[openemr.git] / interface / patient_file / deleter.php
blobfe588d8666da68c4923b55ae597705bb85c8a5ba
1 <?php
2 /**
3 * delete tool, for logging and removing patient data.
5 * Called from many different pages.
7 * Copyright (C) 2005-2013 Rod Roark <rod@sunsetsystems.com>
8 * Copyright (C) 2015 Roberto Vasquez <robertogagliotta@gmail.com>
10 * LICENSE: This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
21 * @package OpenEMR
22 * @author Rod Roark <rod@sunsetsystems.com>
23 * @author Roberto Vasquez <robertogagliotta@gmail.com>
24 * @link http://www.open-emr.org
27 require_once('../globals.php');
28 require_once($GLOBALS['srcdir'].'/log.inc');
29 require_once($GLOBALS['srcdir'].'/acl.inc');
30 require_once($GLOBALS['srcdir'].'/sl_eob.inc.php');
32 $patient = $_REQUEST['patient'];
33 $encounterid = $_REQUEST['encounterid'];
34 $formid = $_REQUEST['formid'];
35 $issue = $_REQUEST['issue'];
36 $document = $_REQUEST['document'];
37 $payment = $_REQUEST['payment'];
38 $billing = $_REQUEST['billing'];
39 $transaction = $_REQUEST['transaction'];
41 $info_msg = "";
43 // Delete rows, with logging, for the specified table using the
44 // specified WHERE clause.
46 function row_delete($table, $where) {
47 $tres = sqlStatement("SELECT * FROM $table WHERE $where");
48 $count = 0;
49 while ($trow = sqlFetchArray($tres)) {
50 $logstring = "";
51 foreach ($trow as $key => $value) {
52 if (! $value || $value == '0000-00-00 00:00:00') continue;
53 if ($logstring) $logstring .= " ";
54 $logstring .= $key . "='" . addslashes($value) . "'";
56 newEvent("delete", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "$table: $logstring");
57 ++$count;
59 if ($count) {
60 $query = "DELETE FROM $table WHERE $where";
61 echo $query . "<br>\n";
62 sqlStatement($query);
66 // Deactivate rows, with logging, for the specified table using the
67 // specified SET and WHERE clauses.
69 function row_modify($table, $set, $where) {
70 if (sqlQuery("SELECT * FROM $table WHERE $where")) {
71 newEvent("deactivate", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "$table: $where");
72 $query = "UPDATE $table SET $set WHERE $where";
73 echo $query . "<br>\n";
74 sqlStatement($query);
78 // We use this to put dashes, colons, etc. back into a timestamp.
80 function decorateString($fmt, $str) {
81 $res = '';
82 while ($fmt) {
83 $fc = substr($fmt, 0, 1);
84 $fmt = substr($fmt, 1);
85 if ($fc == '.') {
86 $res .= substr($str, 0, 1);
87 $str = substr($str, 1);
88 } else {
89 $res .= $fc;
92 return $res;
95 // Delete and undo product sales for a given patient or visit.
96 // This is special because it has to replace the inventory.
98 function delete_drug_sales($patient_id, $encounter_id=0) {
99 $where = $encounter_id ? "ds.encounter = '$encounter_id'" :
100 "ds.pid = '$patient_id' AND ds.encounter != 0";
101 sqlStatement("UPDATE drug_sales AS ds, drug_inventory AS di " .
102 "SET di.on_hand = di.on_hand + ds.quantity " .
103 "WHERE $where AND di.inventory_id = ds.inventory_id");
104 if ($encounter_id) {
105 row_delete("drug_sales", "encounter = '$encounter_id'");
107 else {
108 row_delete("drug_sales", "pid = '$patient_id'");
112 // Delete a form's data from its form-specific table.
114 function form_delete($formdir, $formid) {
115 $formdir = ($formdir == 'newpatient') ? 'encounter' : $formdir;
116 if (substr($formdir,0,3) == 'LBF') {
117 row_delete("lbf_data", "form_id = '$formid'");
119 else if ($formdir == 'procedure_order') {
120 $tres = sqlStatement("SELECT procedure_report_id FROM procedure_report " .
121 "WHERE procedure_order_id = ?", array($formid));
122 while ($trow = sqlFetchArray($tres)) {
123 $reportid = 0 + $trow['procedure_report_id'];
124 row_delete("procedure_result", "procedure_report_id = '$reportid'");
126 row_delete("procedure_report", "procedure_order_id = '$formid'");
127 row_delete("procedure_order_code", "procedure_order_id = '$formid'");
128 row_delete("procedure_order", "procedure_order_id = '$formid'");
130 else if ($formdir == 'physical_exam') {
131 row_delete("form_$formdir", "forms_id = '$formid'");
133 else {
134 row_delete("form_$formdir", "id = '$formid'");
138 // Delete a specified document including its associated relations and file.
140 function delete_document($document) {
141 $trow = sqlQuery("SELECT url FROM documents WHERE id = ?", array($document));
142 $url = $trow['url'];
143 row_delete("categories_to_documents", "document_id = '" . add_escape_custom($document) . "'");
144 row_delete("documents", "id = '" . add_escape_custom($document) . "'");
145 row_delete("gprelations", "type1 = 1 AND id1 = '" . add_escape_custom($document) . "'");
146 if (substr($url, 0, 7) == 'file://') {
147 @unlink(substr($url, 7));
151 <html>
152 <head>
153 <?php html_header_show();?>
154 <title><?php xl('Delete Patient, Encounter, Form, Issue, Document, Payment, Billing or Transaction','e'); ?></title>
155 <link rel="stylesheet" href='<?php echo $css_header ?>' type='text/css'>
157 <style>
158 td { font-size:10pt; }
159 </style>
161 <script language="javascript">
162 function submit_form()
164 document.deletefrm.submit();
166 // Java script function for closing the popup
167 function popup_close() {
168 if(parent.$==undefined) {
169 window.close();
171 else {
172 parent.$.fn.fancybox.close();
175 </script>
176 </head>
178 <body class="body_top">
179 <?php
180 // If the delete is confirmed...
182 if ($_POST['form_submit']) {
184 if ($patient) {
185 if (!acl_check('admin', 'super')) die("Not authorized!");
186 row_modify("billing" , "activity = 0", "pid = '$patient'");
187 row_modify("pnotes" , "deleted = 1" , "pid = '$patient'");
188 // row_modify("prescriptions" , "active = 0" , "patient_id = '$patient'");
189 row_delete("prescriptions" , "patient_id = '$patient'");
190 row_delete("claims" , "patient_id = '$patient'");
191 delete_drug_sales($patient);
192 row_delete("payments" , "pid = '$patient'");
193 row_delete("ar_activity" , "pid = '$patient'");
194 row_delete("openemr_postcalendar_events", "pc_pid = '$patient'");
195 row_delete("immunizations" , "patient_id = '$patient'");
196 row_delete("issue_encounter", "pid = '$patient'");
197 row_delete("lists" , "pid = '$patient'");
198 row_delete("transactions" , "pid = '$patient'");
199 row_delete("employer_data" , "pid = '$patient'");
200 row_delete("history_data" , "pid = '$patient'");
201 row_delete("insurance_data" , "pid = '$patient'");
203 $res = sqlStatement("SELECT * FROM forms WHERE pid = '$patient'");
204 while ($row = sqlFetchArray($res)) {
205 form_delete($row['formdir'], $row['form_id']);
207 row_delete("forms", "pid = '$patient'");
209 // integration_mapping is used for sql-ledger and is virtually obsolete now.
210 $row = sqlQuery("SELECT id FROM patient_data WHERE pid = '$patient'");
211 row_delete("integration_mapping", "local_table = 'patient_data' AND " .
212 "local_id = '" . $row['id'] . "'");
214 // Delete all documents for the patient.
215 $res = sqlStatement("SELECT id FROM documents WHERE foreign_id = '$patient'");
216 while ($row = sqlFetchArray($res)) {
217 delete_document($row['id']);
220 // This table exists only for athletic teams.
221 $tmp = sqlQuery("SHOW TABLES LIKE 'daily_fitness'");
222 if (!empty($tmp)) {
223 row_delete("daily_fitness", "pid = '$patient'");
226 row_delete("patient_data", "pid = '$patient'");
228 else if ($encounterid) {
229 if (!acl_check('admin', 'super')) die("Not authorized!");
230 row_modify("billing", "activity = 0", "encounter = '$encounterid'");
231 delete_drug_sales(0, $encounterid);
232 row_delete("ar_activity", "encounter = '$encounterid'");
233 row_delete("claims", "encounter_id = '$encounterid'");
234 row_delete("issue_encounter", "encounter = '$encounterid'");
235 $res = sqlStatement("SELECT * FROM forms WHERE encounter = '$encounterid'");
236 while ($row = sqlFetchArray($res)) {
237 form_delete($row['formdir'], $row['form_id']);
239 row_delete("forms", "encounter = '$encounterid'");
241 else if ($formid) {
242 if (!acl_check('admin', 'super')) die("Not authorized!");
243 $row = sqlQuery("SELECT * FROM forms WHERE id = '$formid'");
244 $formdir = $row['formdir'];
245 if (! $formdir) die("There is no form with id '$formid'");
246 form_delete($formdir, $row['form_id']);
247 row_delete("forms", "id = '$formid'");
249 else if ($issue) {
250 if (!acl_check('admin', 'super')) die("Not authorized!");
251 row_delete("issue_encounter", "list_id = '$issue'");
252 row_delete("lists", "id = '$issue'");
254 else if ($document) {
255 if (!acl_check('admin', 'super')) die("Not authorized!");
256 delete_document($document);
258 else if ($payment) {
259 if (!acl_check('admin', 'super')) die("Not authorized!");
260 list($patient_id, $timestamp, $ref_id) = explode(".", $payment);
261 // if (empty($ref_id)) $ref_id = -1;
262 $timestamp = decorateString('....-..-.. ..:..:..', $timestamp);
263 $payres = sqlStatement("SELECT * FROM payments WHERE " .
264 "pid = '$patient_id' AND dtime = '$timestamp'");
265 while ($payrow = sqlFetchArray($payres)) {
266 if ($payrow['encounter']) {
267 $ref_id = -1;
268 // The session ID passed in is useless. Look for the most recent
269 // patient payment session with pay total matching pay amount and with
270 // no adjustments. The resulting session ID may be 0 (no session) which
271 // is why we start with -1.
272 $tpmt = $payrow['amount1'] + $payrow['amount2'];
273 $seres = sqlStatement("SELECT " .
274 "SUM(pay_amount) AS pay_amount, session_id " .
275 "FROM ar_activity WHERE " .
276 "pid = '$patient_id' AND " .
277 "encounter = '" . $payrow['encounter'] . "' AND " .
278 "payer_type = 0 AND " .
279 "adj_amount = 0.00 " .
280 "GROUP BY session_id ORDER BY session_id DESC");
281 while ($serow = sqlFetchArray($seres)) {
282 if (sprintf("%01.2f", $serow['adj_amount']) != 0.00) continue;
283 if (sprintf("%01.2f", $serow['pay_amount'] - $tpmt) == 0.00) {
284 $ref_id = $serow['session_id'];
285 break;
288 if ($ref_id == -1) {
289 die(xlt('Unable to match this payment in ar_activity') . ": $tpmt");
291 // Delete the payment.
292 row_delete("ar_activity",
293 "pid = '$patient_id' AND " .
294 "encounter = '" . $payrow['encounter'] . "' AND " .
295 "payer_type = 0 AND " .
296 "pay_amount != 0.00 AND " .
297 "adj_amount = 0.00 AND " .
298 "session_id = '$ref_id'");
299 if ($ref_id) {
300 row_delete("ar_session",
301 "patient_id = '$patient_id' AND " .
302 "session_id = '$ref_id'");
305 else {
306 // Encounter is 0! Seems this happens for pre-payments.
307 $tpmt = sprintf("%01.2f", $payrow['amount1'] + $payrow['amount2']);
308 row_delete("ar_session",
309 "patient_id = '$patient_id' AND " .
310 "payer_id = 0 AND " .
311 "reference = '" . add_escape_custom($payrow['source']) . "' AND " .
312 "pay_total = '$tpmt' AND " .
313 "(SELECT COUNT(*) FROM ar_activity where ar_activity.session_id = ar_session.session_id) = 0 " .
314 "ORDER BY session_id DESC LIMIT 1");
316 row_delete("payments", "id = '" . $payrow['id'] . "'");
319 else if ($billing) {
320 if (!acl_check('acct','disc')) die("Not authorized!");
321 list($patient_id, $encounter_id) = explode(".", $billing);
322 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2) {
323 sqlStatement("DELETE FROM ar_activity WHERE " .
324 "pid = ? AND encounter = ? ", array($patient_id, $encounter_id) );
325 sqlStatement("DELETE ar_session FROM ar_session LEFT JOIN " .
326 "ar_activity ON ar_session.session_id = ar_activity.session_id " .
327 "WHERE ar_activity.session_id IS NULL");
328 row_modify("billing", "activity = 0",
329 "pid = '$patient_id' AND " .
330 "encounter = '$encounter_id' AND " .
331 "code_type = 'COPAY' AND " .
332 "activity = 1");
333 sqlStatement("UPDATE form_encounter SET last_level_billed = 0, " .
334 "last_level_closed = 0, stmt_count = 0, last_stmt_date = NULL " .
335 "WHERE pid = '$patient_id' AND encounter = '$encounter_id'");
337 else {
338 slInitialize();
339 $trans_id = SLQueryValue("SELECT id FROM ar WHERE ar.invnumber = '$billing' LIMIT 1");
340 if ($trans_id) {
341 newEvent("delete", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Invoice $billing from SQL-Ledger");
342 SLQuery("DELETE FROM acc_trans WHERE trans_id = '$trans_id'");
343 if ($sl_err) die($sl_err);
344 SLQuery("DELETE FROM invoice WHERE trans_id = '$trans_id'");
345 if ($sl_err) die($sl_err);
346 SLQuery("DELETE FROM ar WHERE id = '$trans_id'");
347 if ($sl_err) die($sl_err);
348 } else {
349 $info_msg .= "Invoice '$billing' not found!";
351 SLClose();
353 sqlStatement("UPDATE drug_sales SET billed = 0 WHERE " .
354 "pid = '$patient_id' AND encounter = '$encounter_id'");
355 updateClaim(true, $patient_id, $encounter_id, -1, -1, 1, 0, ''); // clears for rebilling
357 else if ($transaction) {
358 if (!acl_check('admin', 'super')) die("Not authorized!");
359 row_delete("transactions", "id = '$transaction'");
361 else {
362 die("Nothing was recognized to delete!");
365 if (! $info_msg) $info_msg = xl('Delete successful.');
367 // Close this window and tell our opener that it's done.
369 echo "<script language='JavaScript'>\n";
370 if ($info_msg) echo " alert('$info_msg');\n";
371 if ($encounterid) //this code need to be same as 'parent.imdeleted($encounterid)' when the popup is div like
373 echo "window.opener.imdeleted($encounterid);\n";
375 else
377 echo " if (opener && opener.imdeleted) opener.imdeleted(); else parent.imdeleted();\n";
379 echo " window.close();\n";
380 echo "</script></body></html>\n";
381 exit();
385 <form method='post' name="deletefrm" action='deleter.php?patient=<?php echo attr($patient) ?>&encounterid=<?php echo attr($encounterid) ?>&formid=<?php echo attr($formid) ?>&issue=<?php echo attr($issue) ?>&document=<?php echo attr($document) ?>&payment=<?php echo attr($payment) ?>&billing=<?php echo attr($billing) ?>&transaction=<?php echo attr($transaction) ?>' onsubmit="javascript:alert('1');document.deleform.submit();">
387 <p class="text">&nbsp;<br><?php xl('Do you really want to delete','e'); ?>
389 <?php
390 if ($patient) {
391 echo xl('patient') . " " . text($patient);
392 } else if ($encounterid) {
393 echo xl('encounter') . " " . text($encounterid);
394 } else if ($formid) {
395 echo xl('form') . " " . text($formid);
396 } else if ($issue) {
397 echo xl('issue') . " " .text($issue);
398 } else if ($document) {
399 echo xl('document') . " " . text($document);
400 } else if ($payment) {
401 echo xl('payment') . " " .text($payment);
402 } else if ($billing) {
403 echo xl('invoice') . " " . text($billing);
404 } else if ($transaction) {
405 echo xl('transaction') . " " . text($transaction);
407 ?> <?php xl('and all subordinate data? This action will be logged','e'); ?>!</p>
409 <center>
411 <p class="text">&nbsp;<br>
412 <a href="#" onclick="submit_form()" class="css_button"><span><?php xl('Yes, Delete and Log','e'); ?></span></a>
413 <input type='hidden' name='form_submit' value=<?php xl('Yes, Delete and Log','e','\'','\''); ?>/>
414 <a href='#' class="css_button" onclick=popup_close();><span><?php echo xl('No, Cancel');?></span></a>
415 </p>
417 </center>
418 </form>
419 </body>
420 </html>